C++中拷贝构造函数调用时机通常有三种情况
使用一个已经创建完毕的对象来初始化一个新对象
值传递的方式给函数参数传值
以值方式返回局部对象
class Person {
public:
Person() {
cout << "无参构造函数调用!" << endl;
mAge = 0;
}
Person(int age) {
cout << "有参构造函数调用!" << endl;
mAge = age;
}
Person(const Person& p) {
cout << "拷贝构造函数调用!" << endl;
mAge = p.mAge;
}
//析构函数在释放内存之前调用
~Person() {
cout << "析构函数!" << endl;
}
public:
int mAge;
};
//1. 使用一个已经创建完毕的对象来初始化一个新对象
void test01() {
Person man(100); //p对象已经创建完毕
Person newman(man); //调用拷贝构造函数
Person newman2 = man; //拷贝构造
cout << "newman的年龄为:"<< newman.mAge <<endl;
//Person newman3;
//newman3 = man; //不是调用拷贝构造函数,赋值操作
}
//2. 值传递的方式给函数参数传值
//相当于Person p1 = p;
void doWork(Person p1) {} // 值传递的本质是拷贝一份临时的副本出来。
void test02() {
Person p; //无参构造函数:默认构造。
doWork(p); // 实参将值传递给形参时,会调用拷贝构造函数,将对象拷贝。
}
//3. 以值方式返回局部对象
Person doWork2()
{
Person p1; // 局部对象:特点:函数执行完之后,就会被释放掉。因此不会返回这个对象。
cout << (int *)&p1 << endl;
return p1; // 但是我们返回的并非是p1本身,而是以值方式来返回,因此在返回时会根据p1创建出一个新的对象。然后返给调用者。
}
void test03()
{
Person p = doWork2();
cout << (int *)&p << endl; // 与doWork中的p1地址不同。
}
int main() {
//test01();
//test02();
test03();
system("pause");
return 0;
}
时机一:使用已创建(已有)完毕的对象,来初始化一个新的对象,这是拷贝构造的最直接应用。
- 基于一个对象,复制构造另一个对象。这种情况要注意区分
时机二:值传递的方式给函数参数传值。
- 值传递的本质是拷贝一份临时的副本出来。实参将值传递给形参时,会调用拷贝构造函数,将对象拷贝复制。
时机三:以值方式返回局部对象。
- 在doWork函数中,对象作为返回值。在函数中,声明的对象,作为局部对象:特点:函数执行完之后,就会被释放掉。因此不能直接返回这个局部对象。
- return的实现方式是:以值方式来返回,在返回时根据p1创建一个新的对象,然后返回给调用者。
- 代码中两次打印对象的地址也确实不同。