拷贝构造函数主要应用在以下场景中:
1 根据一个同类型的对象新建一个对象时。
注意与=赋值运算符的区别,=不会生成一个新的对象。下面实例:
运行结果:
default constructing...
constructing with parameter ...1
operatoring...
copy constructing...
2 复制一个对象,将它作为实参传给一个函数(注意对象引用不会)。
3 从函数返回时复制一个对象(注意对象引用不会)。下面实例:
运行结果:
default constructing...
play1
copy constructing...//实参传给一个函数
copy constructing...//返回一个对象
play2
copy constructing...//返回一个对象
play3
copy constructing...//实参传给一个函数
play4
下面是一道面试题:
运行结果:
constructing with parameter ...1//使用1新建实参s
copy constructing...//返回一个对象,调用复制构造函数
destructing with parameter ...1//参数s析构
destructing with parameter ...1//调用函数main没有定义变量接收返回值,所以会用一个临时对象保存返回的对象的值。被调用函数结束时,临时对象被析构
......
constructing with parameter ...2//使用2新建实参s
copy constructing...//返回一个对象,调用复制构造函数
destructing with parameter ...2//参数s析构
......
default constructing...//Single o3;
constructing with parameter ...3//使用3新建实参s
copy constructing...//返回一个对象,调用复制构造函数
destructing with parameter ...3//参数s析构
operatoring...//赋值
destructing with parameter ...3//临时对象析构
destructing with parameter ...3//o3析构
destructing with parameter ...2//o2析构
下面的例子来自Thinking in C++:
#include <cstdio> #include <iostream> #include <fstream> using namespace std; ofstream out("howmany2.out"); class HowMany2 { string name; // Object identifier static int objectCount; public: HowMany2(const string& id = "") : name(id) { ++objectCount; print("HowMany2()"); } ~HowMany2() { --objectCount; print("~HowMany2()"); } // The copy-constructor: HowMany2(const HowMany2& h) : name(h.name) { name += " copy"; ++objectCount; print("HowMany2(const HowMany2&)"); } void print(const string& msg = "") const { if(msg.size() != 0) out << msg << endl; out << '\t' << name << ": " << "objectCount = " << objectCount << endl; } }; int HowMany2::objectCount = 0; // Pass and return BY VALUE: HowMany2 f(HowMany2 x) { x.print("x argument inside f()"); out << "Returning from f()" << endl; return x; } int main() { HowMany2 h("h"); out << "Entering f()" << endl; HowMany2 h2 = f(h); h2.print("h2 after call to f()"); out << "Call f(), no return value" << endl; f(h); out << "After call to f()" << endl; } ///:~
运行的结果为:
HowMany2()
h: objectCount = 1
Entering f()
HowMany2(const HowMany2&)
h copy: objectCount = 2
x argument inside f()
h copy: objectCount = 2
Returning from f()
HowMany2(const HowMany2&)
h copy copy: objectCount = 3
~HowMany2()
h copy: objectCount = 2
h2 after call to f()
h copy copy: objectCount = 2
Call f(), no return value
HowMany2(const HowMany2&)
h copy: objectCount = 3
x argument inside f()
h copy: objectCount = 3
Returning from f()
HowMany2(const HowMany2&)
h copy copy: objectCount = 4
~HowMany2() //临时对象
h copy copy: objectCount = 3
~HowMany2() //内部对象
h copy: objectCount = 2
After call to f()
~HowMany2()
h copy copy: objectCount = 1
~HowMany2()
h: objectCount = 0
其中临时对象的析构要早于内部对象,而Thinking in C++中顺序相反。总之,临时对象的生存期一定要尽可能的短。