生活随笔
收集整理的这篇文章主要介绍了
c++构造函数以及类中变量初始化顺序
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
c++构造函数以及类中变量初始化顺序
Submitted by
ant on
Fri, 03/29/2013 - 20:05 构造函数 c++ 的类提供了一种抽象机制,使用起来要比 c 方便很多。为了安全等,c++ 中的每一个对象都要经过构造,跑出作用域之外的对象(非 free-store 上的)都要析构,不管是使用自定义的构造/析构函数也好,还是使用默认的。为了对象的正确拷贝构造或是赋值,me 们要自己写拷贝构造函数/拷贝赋值,为了所谓的效率,还得自己写移动构造函数/移动赋值。默认生成的若干个函数有:
Test(); // 默认构造函数,可以不带参数的构造函数,T t;
Test(Test& t); // 拷贝构造函数,T t2 = t;
Test(Test&& t); // 移动构造函数,T t3 = fun(); fun() 返回一个 T 的临时对象
Test& operate=(Test& t); // 拷贝赋值,t3 = t2;
Test& operate=(Test&& t); // 移动赋值,t2 = fun();
~Test(); // 析构函数
默认构造函数比较简单,两个移动 (move) 函数是 c++11 中加入的,其实也可以先不关心,拷贝赋值也先不关心,就说拷贝构造函数,神马时候会调用的问题,根据 wiki 的说法:
直接使用一个对象构造一个对象,如 T t2 = t; 或是 T t2(t); 将一个对象以值(不是引用)的形式递给一个函数,比如 test(t); 将函数中的一个对象的值(不是引用)传递出函数外,比如 fun(); throw 一个对象,catch 一个对象的值(不是引用); 基本规则是上面说的,但是却不是总是那样,据说 c++标准允许编译器优化拷贝,实际上 gcc 在函数返回值是否拷贝的问题上很多时候跟 vc++ 就不一致。有一项技术叫 RVO (return value optimization ) —— 返回值优化,貌似就是说的那个。me 的实际运行结果是:gcc 在函数返回一个对象的值的时候可能不调用拷贝构造函数/移动构造函数,而 vc++ 就要循规蹈矩得多一些,虽然说是数据多拷了几次。 真的是 maybe,即使是 vc++ 在函数中直接 return T(); 和 Test t; return t; 结果都可能不一样,gcc 中的结果可能更离奇一点。
很多时候真不用关心这一点细节问题,拷贝也不会出什么问题。不过拷贝构造 maybe 有“副作用”,比如不是等值拷贝,而是放大一倍拷贝,这个时候,如果拷贝构造函数调用的次数都不一样,程序结果可能就不一样,实际上是,结果的确就不一样!所以,拷贝还是尽可能遵循原有的“语义”,等值拷贝,否则都是合法的 c++程序,在 vc 和 gcc 中结果不一样让人有些惊讶!
现在说,移动构造的问题,可以先看下右值引用。有了移动构造的话,有时候就影响拷贝构造,比如 T t=fun(); 以前肯定会说是调用“拷贝构造函数”,现在就不一定了,可能就是“移动构造函数”了,也就是直接将返回来的临时对象,作为新构造的对象使用;而按其那面 gcc 的逻辑,可能这里神马“构造函数”都不调用,因为就没有构造!如果说对于 A a = testA(); 会调用“移动构造”,而 B b = testB(); 却不调用“移动构造”,这也令 me 很震惊,都是返回一个临时对象,都有移动构造函数,为嘛有时候就调用,有时候就不调用?O__O"…竟然跟里面是神马变量有关?!!!可以修改下面的程序,自己看运行结果:(移动构造是 c++11 新加的,gcc 编译的话,需要加上 -std=c++11,or =std=c++0x)。
#include <iostream> using namespace std; class Test{ public : Test( ) { value = 0 ; cout << "default constructor." << "\n " ; } Test( Test& t) { value = 42 ; cout << "non-const copy constructor." << "\n " ; } // can modify t.value ! Test( const Test& t) { cout << "const copy constructor." << "\n " ; } Test( Test&& t) : value( t.value ) { cout << "move constructor." << "\n " ; } ~Test( ) { cout << "destructor." << "\n " ; } int getValue( ) { return value; } ; private : int value; } ; Test fun( Test tmp) { Test a; return a; } int main( ) { Test a; cout << "a.value:" << a.getValue ( ) << "\n " ; Test b = fun( a) ; cout << "b.value:" << b.getValue ( ) << "\n " ; Test c = a; cout << "c.value:" << c.getValue ( ) << "\n " ; return 0 ; } 类中变量的初始化顺序 c++ 中类变量的初始化顺序,大体如下:
基类的静态成员初始化; 派生类的静态成员初始化; 基类的对象成员初始化; 基类的构造函数; 派生类的对象成员初始化; 派生类的构造函数; 貌似 c++11 允许类中变量直接初始化,跟 Java 的使用方法类似,me 么试过。其次,类中对象成员的初始化顺序跟构造函数中初始化列表的顺序无关,只跟声明时候的顺序有关。
测试程序:
#include <iostream> using namespace std; class Inner{ public : Inner( int i= 0 ) : in( i) { cout << "Inner.constructor." << "\n " ; } Inner( Inner& inner) : in( inner.in ) { cout << "Inner.copy consturctor" << "\n " ; } ; int getValue( ) { return in; } private : int in; } ; class Inner2{ public : Inner2( double i= 0.0 ) : in2( i) { cout << "Inner2.constructor." << "\n " ; } Inner2( Inner2& inner2) : in2( inner2.in2 ) { cout << "Inner2.copy consturctor" << "\n " ; } ; int getValue( ) { return in2; } private : double in2; } ; class Base{ public : Base( int v= 0 ) : value( v) { value = 1 ; cout << "Base.constructor." << "\n " ; } Base( Base& b) : value( b.value ) { cout << "Base.copy consturctor" << "\n " ; } int getValue( ) { return value; } protected : int value; } ; class Derive: public Base{ public : // Derive(string s = "hello", int base=0, int i=0, double i2=0): derive(s), in2(i2), in(i) { cout << "derive.derive == " << derive << ", Derive.consturctor" << "\n";}; Derive( string s = "hello" , int base= 0 , int i= 0 , double i2= 0 ) { cout << "Derive.consturctor" << "\n " ; } ; Derive( Derive& d) : derive( d.derive ) { cout << "Derive.copy consturctor" << "\n " ; } void printValue( ) { cout << "derive.base.value == " << value << ", derive.derive == " << derive << ", derive.in == " << in.getValue ( ) << ", derive.in2 == " << in2.getValue ( ) << "\n " ; } private : string derive; Inner in; Inner2 in2; } ; int main( ) { Derive d( "world" , 10 , 20 , 30.0 ) ; d.printValue ( ) ; // Derive d2 = d; cout << endl; }
总结
以上是生活随笔 为你收集整理的c++构造函数以及类中变量初始化顺序 的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔 网站内容还不错,欢迎将生活随笔 推荐给好友。