什么是拷贝构造函数
拷贝构造函数是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显示使用拷贝构造函数。当该类型的对象传递给函数或从函数返回该类型的对象时,将隐式调用拷贝构造函数。
class Person
{
public:
Person(const Person& p){//拷贝构造函数
return *this;
}
Person& operator=(const Person& p);//重载赋值操作符
};
拷贝构造函数和赋值函数的区别
拷贝构造函数是一个对象初始化一块内存区域,这块内存就是新对象的内存区,而赋值函数是对于一个已经被初始化的对象来进行赋值操作。
Person t1;
t1=f();//这是赋值函数
Person t2=f();//这是复制构造函数
啥时候用拷贝构造函数
- 一个对象以值传递的方式传入函数体
- 一个对象以值传递的方式从函数返回
- 一个对象需要通过另外一个对象进行初始化。
以值传递的方式传入函数体
f(Person t2){};
f(t1);//将t1复制给t2,调用拷贝构造函数!
f(){
Person t3;
return t3;//首先构造t3,构造函数,
//然后将t3复制到一个临时对象,调用拷贝构造函数
}
注意:下面这种情况在传参的过程中,没调用
Person(int a){}
f(Person t1){
}
f(3);//这个传参过程中只调用了构造函数,没有调用拷贝构造函数,编译器会尽量减少多余的操作
以值传递的方式从函数返回
那就是说在返回的过程中会调用一次拷贝构造函数,那出现如下情况
f(){
Person t3;
return t3;//首先构造t3,构造函数,
}
Person t4=f();
//这调用拷贝函数,但只调用一次,而不是两次,省略了到临时对象的过程,所以次序为
//构造函数t3,拷贝构造函数t4,析构t3
与之类似的,假如不是拷贝调用,是赋值函数
f(){
Person t3;
return t3;//首先构造t3,构造函数,
}
Person t4;
t4=f();
//这明显是赋值函数,因此需要临时对象的参与,
//次序为:构造函数t3,拷贝构造函数临时对象,赋值函数,析构函数t3,析构函数临时对象
还有种情况,这个f返回值没人要
f(){
Person t3;
return t3;//首先构造t3,构造函数,
}
f();
//这就是调用一次拷贝构造函数,构造了临时对象,然后没人要这个临时对象,自己析构了
//次序为:构造函数t3,拷贝构造函数临时对象,析构函数t3,析构函数临时对象
部分代码测试
测试1
#include <iostream>
using namespace std;
class B
{
public:
B(){cout<<"构造函数B"<<endl;}
B(int i):data(i){cout<<"构造函数B"<<data<<endl;}
B play(B b){
cout<<"fwkj"<<endl;
return b;
}
B(const B&b){
cout<<"拷贝构造函数"<<endl;
}
~B(){cout<<"析构函数B"<<endl;}
B& operator=(const B& b){
cout<<"等于号"<<endl;
return *this;
}
private:
int data;
};
int main()
{
B temp;
B t3;
t3=temp.play(5);
return 0;
}
结果:
构造函数B
构造函数B
构造函数B5
fwkj
拷贝构造函数
等于号
析构函数B
析构函数B
析构函数B
析构函数B
测试2
#include<iostream>
class TestConstructor
{
public:
TestConstructor()
{
std::cout << "TestConstructor()" << std::endl;
}
~TestConstructor()
{
std::cout << "~TestConstructor()" << std::endl;
}
TestConstructor(const TestConstructor& testObj)
{
std::cout << "TestConstructor(const TestConstructor&)" << std::endl;
}
TestConstructor& operator = (const TestConstructor& testObj)
{
std::cout << "TestConstructor& operator = (const TestConstructor& testObj)" << std::endl;
return *this;
}
};
TestConstructor testFunc()
{
TestConstructor testInFunc; //3、调用TestConstructor() 生成对象testInFunc
return testInFunc; //4、调用TestConstructor(const TestConstructor&) 生成临时对象
//5、调用析构函数,析构对象testInFunc
}
int main()
{
TestConstructor test; //1、调用TestConstructor() 生成对象test
test = testFunc(); //2、调用testFunc() //6、调用等号把临时对象复制给对象test //7、调用析构函数,析构临时对象
return 0; //8、调用析构函数,析构对象test
}