C++资源
https://isocpp.org/blog/2014/03/compiler-support-for-c11-and-c14
推荐工具软件——DASH。这个查语言特性特别快。只可惜只能在苹果系的产品中使用。
关键字
/* key words of cpp
* alignas (C++11 起)
* alignof (C++11 起)
* and
* and_eq
* asm
* auto
* bitand
* bitor
* bool
* break
* case
* catch
* char == unsigned char linux signed char
* char16_t(C++11 起)Unicode utf8
* char32_t(C++11 起)Unicode
* class
* compl ~
* concept (概念TS)
* const multithread
* constexpr(C++11 起)
* const_cast
* continue
* decltype(C++11 起)
* default (normal use speical use)
* delete
* do
* double
* dynamic_cast
* else
* enum
* explicit
* export
* extern
* false
* float
* for
* friend
* goto
* if
* inline
* int signed
* long
* mutable
* namespace
* new
* noexcept(C++11 起)
* not !
* not_eq !=
* nullptr (C++11 起)
* operator + - ||
* or ||
* or_eq |=
* private
* protected
* public
* register
* reinterpret_cast
* requires(概念TS)
* return
* short
* signed
* sizeof
* static
* static_assert(C++11 起)
* static_cast
* struct
* switch
* template
* this
* thread_local(C++11 起)
* throw
* true
* try
* typedef
* typeid
* typename
* union
* unsigned
* using
* virtual
* void
* volatile
* wchar_t
* while
* xor ^
* xor_eq ^=
* */
alignas——取值是2的幂次
用来对结构体或者类设置对齐方式
struct alignas(8) S {};
//下面的是错误的,因为S的对其凡事要求是8,因此,U的对齐方式不能小于8
struct alignas(1) U { S s; };
alignof
用来获取结构体是按照多少字节对齐的
struct Obj {
char a;
int b;
};
sizeof(Obj);//8
alignof(Obj);//4 因为结构体Obj是按四字节对齐的
测一测
struct Foo {
int i;
float f;
char c;
};
class Empty{};
struct alignas(64) Empty64 {};
struct alignas(1) Double { doubel i; };
struct Obj {
char a;
int b;
};
void alignInof() {
cout << alignof(char) << endl;
cout << alignof(int *) << endl;//64位平台是8,32位平台是4
cout << alignof(Foo) << endl;//4,因为int是4,float也是4
cout << alignof(Empty) << endl;//1
cout << alignof(Empty64) << endl;//64
cout << alignof(Double) << endl;//8,虽然设置的对齐数是1,但是double占8字节
}
bitand和bitor
按位与和按位或
#include<iostream>
using namespace std;
int main(){
auto a=3L;
auto b=4;
//按位与的过程中,b转型为长整型,因此c的类型也是长整型
auto c=a bitand b;
auto d=a bitor b;
cout<<"type of c :"<<typeid(c).name()<<endl;
cout<<"type of b:"<<typeid(b).name()<<endl;
cout<<"value of c:"<<c<<endl;
cout<<"value of d:"<<d<<endl;
return 0;
}
constexpr
用代码求阶乘的方法如下
int fact(int n) {
return n < 1? 1: (n * fact(n-1));
}
我们将其进行修改
constexpr int factorial(int n) {
return n <= 1 ? 1 : (n * factorial(n - 1));
}
此时,对于阶乘的求解会发生如下变化:
- 编译期,如果传入的参数n的值在编译器可以确定出来,则在编译器直接求出函数的结果。
- 求出结果之后,在运行期就直接将结果放在了调用该函数的地方
未完待续,constexpr的其他特性在以后进行补充
const_cast——将const类型变成非const类型
如果代码中出现const_cast,说明代码的结果或者风格可能有一些问题。
const的不变性可以通过const_cast来改变。
void testConstCast(){
const int i=3;
int *p=const_cast<int*>(&j);
*p=4;
}
decltype
为变量设置类型。
下面代码中是decltype的两种使用方式:
struct A{ double x; };
void testDecl(){
const A* a = new A{0};
decltype (a->x) y; //y的类型为double,因为a->x的类型是double
decltype ((a->x)) z=y; //z的类型的double&,cpp里面,对于decltype,带括号的就是获取引用
}
后置返回值类型
(cpp 11新特性。返回值类型由计算结果决定,防止返回值精度的丢失。)
template<typename T, typename U>
auto add(T a, U b) -> decltype(a+b){
return a+b;
}
为什么不能写成
template<typename T, typename U>
decltype(a+b) add(T a, U b){
return a+b;
}
因为编译器运行到decltype那一行的时候,读到a,但是a的类型此时还未声明,因此,编译器会报错。
在cpp14中,对于后置返回值类型进行了简化。因此代码可以这么写:
template<typename T, typename U>
auto add(T a, U b){
return a+b;
}
再次强调一遍,注意()(PS:代码是伪代码,只是为了表达意思,一个函数里面是不能这么写两个return 语句的)
template<typename T, typename U>
auto add(T a, U b){
auto c=a+b;
return c; //返回值类型是c的类型
return (c); //返回值类型是c的引用。如果c是int类型,则该返回值类型是int&
}
但是如果写成cpp 11版本的返回值后置,则上述两种的返回值类型由decltype语句决定,即
template<typename T, typename U>
auto add(T a, U b) -> decltype(a+b){
auto c=a+b;
return c; //返回值类型是decltype(a+b)的类型
return (c); //返回值类型是decltype(a+b)的类型
}
dynamic_cast——将父类指针转换成子类指针
- dynamic_cast对于引用,如果转换失败,则抛出异常
- dynamic_cast对于指针,如果转换失败,则返回空指针
- dynamic_cast会在转化过程中会进行安全检查,因此会比其他cast更安全
dynamic_cast的详细解释见:(占位,以后专门写篇博客补在这里)
struct Base{virtual ~Base(){}};
struct Derived : Base {
virtual void name() {}
};
void testDyn() {
Base *b1 = new Base;
//如果dynamic_cast转换失败,则会返回空指针
if (Derived *d = dynamic_cast<Derived *>(b1)) {
std::cout << "downcast from b1 to d successful\n";
d->name(); // safe to call
}
Base *b2 = new Derived;
//如果dynamic_cast转换成功,则会返回该类型的指针(非空)
if (Derived *d = dynamic_cast<Derived *>(b2)) {
std::cout << "downcast from b2 to d successful\n";
d->name(); // safe to call
}
Base bb;
//dynamic_cast对于引用,如果转换失败,则抛出异常
Derived& cc = dynamic_cast<Derived&>(bb);
}