1. alignas (c++11)
設置類和struct的字節對齊方式
默認取值是: 2n : 0, 1, 2, 4 , 6, 8.....
2. alignof
區分sizeof(), alignof得到字節對齊的字節數
#include <iostream> using namespace std; //對結構體或類進行表示, 設置對齊方式為8字節 struct alignas(8) S {}; //struct alignas(1) U { S s; } // warning //有字節對齊(以4字節為對齊方式) struct Foo { int i; float f; char c; }; struct Empty {}; struct alignas(64) Empty64 {}; struct alignas(1) Double { double d; }; //以四字節為對齊方式, 即sizeof(Obj) == 8 struct Obj { char a; int b; }; void alignInfo() { cout << "sizeof(Obj) : " << sizeof(Obj) << endl; // 8 cout << "alignof(Obj) : " << alignof(Obj) << endl; // 4 cout << "sizeof(Foo) : " << sizeof(Foo) << endl; // 12 cout << "sizeof(Double) : " << sizeof(Double) << endl; // 8 cout << "sizeof(Empty64) : " << sizeof(Empty64) << endl; // 64 cout << "\n"; cout << "Alignment of " << endl; cout << "- char : " << alignof(char) << endl; // 1 cout << "- pointer : " << alignof(int*) << endl; // 8 cout << "- class Foo : " << alignof(Foo) << endl; // 4 cout << "- empty class : " << alignof(Empty) << endl; // 1 cout << "- alignas(64) Empty: " << alignof(Empty64) << endl; // 64 cout << "- alignas(1) Double: " << alignof(Double) << endl; // 8 } int main() { alignInfo(); return 0; }
3. auto (c++11)
#include <iostream> using namespace std; double add(double a, double b) { return a + b; } double get_fun(int a) { return a; } void showAuto() { int aa = 1 + 2; auto a = 1 + 2; cout << "type of a: " << typeid(a).name() << endl; auto b = add(1, 1.2); cout << "type of b: " << typeid(b).name() << endl; auto c = {1, 2}; cout << "type of c: " << typeid(c).name() << endl; auto my_lambda = [](int x) { return x + 3; }; std::cout << "my_lambda: " << my_lambda(5) << endl; auto my_fun = get_fun(2); cout << "type of my_fun: " << typeid(my_fun).name() << endl; cout << "my_fun: " << get_fun(3) << endl; } int main() { showAuto(); return 0; }
4. bitand 和 bitor
#include <iostream> using namespace std; void showBitAndOr() { auto a = 3L; auto b = 4; //long auto c = a bitand b; // & auto d = a bitor b; // | cout << c << endl; cout << d << endl; } int main() { showBitAndOr(); return 0; }
5. constexpr: 常量表達式(c++11)
- 用於編譯時的常量與常量函數。
- 聲明為constexpr函數的意義是:如果其參數均為合適的編譯期常量,則對這個constexpr函數的調用就可用於 期望常量表達式 的場合(如模板的非類型參數,或枚舉常量的值)。
#include <iostream> #include <cstdlib> #include <cstdio> using namespace std; 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)); } template<int N> struct NN { void print() { cout << N << endl; } }; int main(int argc, char *argv[]) { //在編譯器編譯時調用的 if (argc > 1) factorial(atoi(argv[1])); auto aa = fact(4); auto bb = factorial(2); char group[factorial(3)]; //編譯器在編譯時, 就求出來了 NN<factorial(3)> nn; nn.print(); return 0; }
輸出: 6
6. const_cast(避免使用)
7. decltype指定符(c++11)
檢查實體的聲明類型或表達式的類型及值分類。
#include <iostream> #include <cstdlib> #include <cstdio> using namespace std; struct A { double x; A(double t) : x(t) {} }; void testDecltype() { A* a = new A(0); auto aa = a->x; // aa : double decltype(a->x) y; // decltype(a->x) : double decltype((a->x)) z = y; // decltype((a->x)) : double& z = 23.5; cout << y << endl; // 23.5 //其他用法 } //c++11, 后置返回類型, 返回值類型由 后面的表達式確定的 //返回值不損失任何精度 template<typename T, typename U> auto add(T a, U b) -> decltype(a + b) { return a + b; } template<typename T, typename U> auto add(T a, U b) { auto c = a + b; //return c; //返回值 //return (c); //返回引用 return c; } int main(int argc, char **argv) { testDecltype(); return 0; }
8. dynamic_cast轉換
沿繼承層級向上、向下及側向轉換到類的指針和引用。
#include <iostream> #include <cstdlib> #include <cstdio> using namespace std; struct Base { virtual ~Base() {} }; struct Derived : public Base { virtual void name() {} }; void testDynatic_cast() { Base *b1 = new Base(); //擁有基類指針, base指針-->derived指針, 失敗 if (Derived *d = dynamic_cast<Derived *> (b1)) { cout << "donwcast from b1 to d successful\n"; d->name(); // safe to call } Base *b2 = new Derived(); //成功, 因為b2的確指向derived if (Derived *d = dynamic_cast<Derived *> (b2)) { cout << "donwcast from b2 to d successful\n"; d->name(); // safe to call } } int main(int argc, char **argv) { testDynatic_cast(); return 0; }
9. explicit
struct A { A(int) { } // 轉換構造函數
A(int, int) { } // 轉換構造函數 (C++11)
operator bool() const { return true; } }; struct B { explicit B(int) { } explicit B(int, int) { } explicit operator bool() const { return true; } }; int main() { A a1 = 1; // OK :復制初始化選擇 A::A(int)
A a2(2); // OK :直接初始化選擇 A::A(int)
A a3 {4, 5}; // OK :直接列表初始化選擇 A::A(int, int)
A a4 = {4, 5}; // OK :復制列表初始化選擇 A::A(int, int)
A a5 = (A)1; // OK :顯式轉型進行 static_cast
if (a1) ; // OK :A::operator bool()
bool na1 = a1; // OK :復制初始化選擇 A::operator bool()
bool na2 = static_cast<bool>(a1); // OK :static_cast 進行直接初始化 // B b1 = 1; // 錯誤:復制初始化不考慮 B::B(int)
B b2(2); // OK :直接初始化選擇 B::B(int)
B b3 {4, 5}; // OK :直接列表初始化選擇 B::B(int, int) // B b4 = {4, 5}; // 錯誤:復制列表初始化不考慮 B::B(int,int)
B b5 = (B)1; // OK :顯式轉型進行 static_cast
if (b2) ; // OK :B::operator bool() // bool nb1 = b2; // 錯誤:復制初始化不考慮 B::operator bool()
bool nb2 = static_cast<bool>(b2); // OK :static_cast 進行直接初始化
}
10. static_assert: 編譯時檢查
#include <iostream> using namespace std; template<typename T> void func(T t) { static_assert(alignof(T) == 4, "only for alignof 4"); } int main() { int a = 3; func(a); return 0; }