拷贝构造函数主要应用在以下场景中:
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++中顺序相反。总之,临时对象的生存期一定要尽可能的短。