被c++的复杂坑了一把。。
以下为初学者的一些见解吧
首先贴上实验代码:
#include <iostream>
using namespace std;
class Test{
public:
static int c;//用于计数对象
int id;//使用id标识对象
Test(const Test &a){//拷贝构造函数
id = c++;
cout << "This is copy constructor :" << a.id<< endl;
}
Test(){//空参构造函数
id = c++;
cout << "This is null constructor." << endl;
}
~Test(){//析构函数
cout << "This is destory:" << id << endl;
}
Test& operator =(const Test& t){//=运算符重载
id = c++;
cout << "= :" << t.id << endl;
return *this;
}
void print(){cout << "print:" << id << endl;}
};
int Test::c = 1;
Test Get(Test a){
cout << "This is Get()\n";
return a;
}
int main(){
cout << "Start.\n";
Test t1 = Test(Test());
t1.print();
Get(t1);
Test t2 = Get(t1);
t2.print();
t1 = t2;
t1.print();
cout << "End.\n";
}
/*输出:
Start.
This is null constructor.
print:1
This is copy constructor :1
This is Get()
This is copy constructor :2
This is destory:3
This is destory:2
This is copy constructor :1
This is Get()
This is copy constructor :4
This is destory:4
print:5
= :5
print:6
End.
This is destory:5
This is destory:6
Process returned 0 (0x0) execution time : 0.117 s
Press any key to continue.
*/
下面一步一步来解析,看完大概就能理解了吧:)
/一
cout << "Start.\n";
Test t1 = Test(Test());
t1.print();
这里的输出结果是:
Start.
This is null constructor.
print:1
这里看起来像是用一个Test()匿名对象“拷贝构造”了一个匿名对象,然后初始化了t1,实际情况是只创建了一个对象(t1的ID是1,而不是其他),说明其中进行了一次构造,并没有调用拷贝构造。并且匿名对象并没有进行析构,说明是只构建了一个匿名对象并且该匿名对象直接“变”成了t1。
/二
Test Get(Test a){
cout << "This is Get()\n";
return a;
}
Get(t1);
这里输出结果是:
This is copy constructor :1
This is Get()
This is copy constructor :2
This is destory:3
This is destory:2
可以看出,传递进Get函数时使用了一次拷贝构造,拷贝了对象(id=1)(即为t1)给对象(id=2)(即为函数的形参),然后执行Get(),Get的返回值被传递进了一个随机的未知空间并通过拷贝构造创建了对象(id=3)(由对象id=2复制所得),之后函数的形参(id=2)以及未知的对象(id=3)被析构。
///三
Test t2 = Get(t1);
t2.print();
这里输出结果是:
This is copy constructor :1
This is Get()
This is copy constructor :4
This is destory:4
print:5
Get()执行和二类似,但是在析构的时候只析构了函数的形参(id=4),在实验二中的Get()会产生的未知的对象没有被析构,初始化的t2的id=5,并且在Get结束阶段拷贝构造函数只执行了一次且没有执行赋值函数,说明Get()结束阶段生成的那个未知对象是通过拷贝构造函数初始化的匿名对象, 此时这个对象id=5,将t2进行了初始化。
//四
t1 = t2;
t1.print();
cout << "End.\n";
输出结果:
= :5
print:6
End.
This is destory:5
This is destory:6
这里将t2(id=5),通过赋值函数赋值给了t1,t1的id更新为6
随后将程序结束,将t1,t2进行了析构。
结论:
1.普通函数的形参(通过非引用传递)是通过拷贝构造函数创建的,并在函数结束时被析构
2.普通函数的返回值是通过形参拷贝构造了一个匿名函数(只考虑此文章中情况)
3.多个匿名对象空参初始化的嵌套实际只会生成一个匿名对象。
4.通过匿名对象的初始化并不会通过拷贝构造或者赋值函数
5.通过匿名对象的初始化实际上是将要初始化的对象指向了匿名函数所在的内存空间
ps:我只是初学者,可能有错,理解不到位,求大佬订正,勿喷