C++11 关于右值引用、左值引用和通用引用的思考

一、通用引用 类型声明形式为 type&& 其中 type 类型是要进行推导的,如果类型推导没有发生,那么 type&& 代表一个右值引用 如果一个对象被声明为 auto&&,这个形参或者对象就是一个通用引用 通用引用,如果它被右值初始化,就会对应地成为右值引用;如果它被左值初始化,就会成为左值引用 如果在一个类模板里面看见了一个函数形参类型为 T&&,也不一定就是通用引用,可能并没有发生类型推导 void f(Widget&& param); //右值引用 Widget&& var1 = Widget(); //右值引用 auto&& var2 = var1; //通用引用(不是右值引用) template<typename T> void f(std::vector<T>&& param); //右值引用 template<typename T> void f(T&& param); //通用引用(不是右值引用) template <typename T> void f(const T&& param); //param是一个右值引用,因为添加了 const 限定符 // 函数模板 一般可能是通用引用 template <typename T> void print_reference_type(T &&i) { // T&& 或是 auto&& if (std::is_lvalue_reference<decltype(i)>::value) { std::cout << "lvalue: " << i << std::endl; } else if (std::is_rvalue_reference<decltype(i)>::value) { std::cout << "rvalue: " << i << std::endl; } else { std::cout << "unknown value: " << i << std::endl; } } // 因为 push_back 在有一个特定的 vector 实例之前不可能存在, // 而实例化 vector 时的类型已经决定了 push_back 的声明 // 所以在这里并没有发生类型推导 template<class T, class Allocator = allocator<T>> //来自C++标准 class vector { public: void push_back(T&& x); … } 一个记录任意函数调用的时间开销的函数模板...

June 11, 2022 · 2 min · Rick Cui

C 实现继承和多态

C中的继承和多态

May 24, 2022 · 1 min · Rick Cui

C++11 继承构造

通过 using 可以方便的使用父类的构造函数和其他函数; 优先使用子类的构造和函数,如果没有找到匹配的才会调用基类的; 可在子类的初始化列表中调用父类的构造函数,并对子类的成员进行列表初始化; class BS { int q; double w; public: BS() : q(0), w(0) {} BS(int k) : q(k), w(100) {} BS(double x) : q(-1), w(x) {} BS(int k, double x) : q(k), w(x) {} void Show() const { std::cout << q <<", " << w << '\n'; } int fn(int j) { cout << "BS::fn(int)\n"; return 0; } double fn(double w) { cout << "BS::fn(double)\n"; return 0; } void fn(const char * s) { cout << "BS::fn(const char *)\n"; } }; class DR : public BS { short j; public: using BS::BS; DR() : j(-100) {} // DR needs its own default constructor DR(double x) : BS(2*x), j(int(x)) {} DR(int i) : j(-2), BS(i, 0....

May 13, 2022 · 2 min · Rick Cui

C++11 委托构造

委托构造的使用方法类似成员列表初始化的变种; 注意: 如果在一个构造函数中使用了本类的委托构造,就不能再对成员使用列表初始化了; 会先执行委托构造函数的函数体,然后再执行本身的函数体; 虽然可以在构造函数中调用其他的构造函数,但已经被初始化的成员变量还会被当前的构造函数进行重置,有可能导致又变为原来的未初始化状态; class Test{ public: Test():Test(0, 0.1){ s = "Ah"; cout << "Test()\n"; } Test(int ii):Test(ii, 0.1, "Hi"){ cout << "Test(int)\n"; } Test(int ii, double dd):Test(ii, dd, "Hi"){ cout << "Test(int, double)\n"; } Test(int ii, double dd, string ss):i(ii), d(dd), s(ss){ cout << "Test(int, double, string)\n"; } void print(){ cout << "i = " << i << "\td = " << d << "\ts = " << s << endl; } private: int i; double d; string s; }; int main() { Test t(10); t....

May 13, 2022 · 1 min · Rick Cui

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