C++11 内存对齐 alignof alignas max_align_t

alignof( type-id ) 查询类型的对齐要求,以字节为单位 struct Storage { char a; int b; double c; long long d; }; // struct alignas(alignof(long double)) AlignasStorage { // struct alignas(long double) AlignasStorage { struct alignas(std::max_align_t) AlignasStorage { // max_align_t 相当于 alignof(long double) 内存对齐为 16 字节 // 这三种写法都可以 char a; int b; double c; long long d; }; struct Empty {}; struct alignas(64) Empty64 {}; int main() { std::cout << alignof(Storage) << std::endl; // 8 std::cout << sizeof(Storage) << std::endl; // 24 内存对齐为 8 字节,所以大小为 8 的整数倍 std::cout << alignof(AlignasStorage) << std::endl; // 16 std::cout << sizeof(AlignasStorage) << std::endl; // 32 内存对齐为 16 字节,所以大小为 16 的整数倍 int a = 10; int &b = a; std::cout << alignof(b) << std::endl; // 4 引用类型返回引用类型的对齐要求 int x[10]; std::cout << alignof(x) << std::endl; // 4 数组类型返回元素类型的对齐要求 std::cout << "Alignment of" "\n" "- char : " << alignof(char) << "\n" // 1 "- pointer : " << alignof(int*) << "\n" // 8 "- int : " << alignof(int) << "\n" // 4 "- long long : " << alignof(long long) << "\n" // 8 "- empty class : " << alignof(Empty) << "\n" // 1 "- alignas(64) Empty: " << alignof(Empty64) << "\n"; // 64 return 0; }

April 19, 2022 · 1 min · Rick Cui

C++17 折叠表达式

一元折叠表达式 ( pack op ... ) : 一元右折叠 (E op ...) 展开后: (E1 op (... op (EN-1 op EN))) ( ... op pack ) :一元左折叠 (... op E) 展开后: (((E1 op E2) op ...) op EN) 二元折叠表达式 ( pack op ... op init ) :二元右折叠 (E op ... op I) 展开后: (E1 op (... op (EN−1 op (EN op I)))) ( init op ....

April 13, 2022 · 3 min · Rick Cui

C++17 变长参数模板

任意个数、任意类别的模板参数 template<typename... Ts> class Magic; // 计算参数的个数 template<typename... Ts> void magic(Ts... args) { std::cout << sizeof...(args) << std::endl; } 递归解包: C++17 之前 template<typename T0> void my_printf(T0 value) { std::cout << value << std::endl; } template<typename T, typename... Ts> void my_printf(T value, Ts... args) { std::cout << value << std::endl; my_printf(args...); } int main() { my_printf(1, 2.2, "abc", 'a'); return 0; } C++17 变参模板展开: template<typename T, typename....

April 13, 2022 · 1 min · Rick Cui

C++17 使用结构化绑定来解包绑定的返回值

注意:使用结构化绑定时,就不能再使用 std::tie 创建虚拟变量了,所以我们不得不绑定所有值到命名过的变量上。对部分成员进行绑定的做法是高效的,因为编译器可以很容易的对未绑定的变量进行优化 std::pair<int,int> divide_remainder(int dividend, int divisor){ int f = dividend / divisor; int s = dividend % divisor; return {f, s}; } int main() { auto [dividend, remainder] = divide_remainder(16, 3); std::cout << "16 / 3 is " << dividend << " with a remainder of " << remainder << '\n'; // 之前的写法 int remainder1; std::tie(std::ignore, remainder1) = divide_remainder(16, 5); std::cout << "16 % 5 is " << remainder1 << '\n'; return 0; }

April 12, 2022 · 1 min · Rick Cui

C++17 大括号初始化

( expression-list ):优先调用非聚合初始化,且会存在隐式转换 = expression: { initializer-list }:如果有聚合初始化(initializer_list<>),就调用聚合初始化,没有的话就调用符合条件的非聚合初始化 = { initializer-list }:同上 使用 auto 声明的变量括号初始化,只允许一个参数的情况 {} 与 () 调用构造函数初始化的方式,不同点在于 {} 没有类型的隐式转换,比如 int x(1.2); 和 int x = 1.2; 通过隐式的对浮点值进行向下取整,然后将其转换为整型,从而将 x 的值初始化为 1。相反的, int x{1.2}; 将会遇到编译错误,初始化列表中的初始值,需要与变量声明的类型完全匹配。 测试代码一: // #define AGGREGATE_INIT class Test{ public: Test(int a, float b, char* c){ cout << "int float char* initialize..." << endl; } Test(int a, int b, int c){ cout << "int int int initialize....

April 12, 2022 · 2 min · Rick Cui