本文测试内容大部分都是参考该博文 https://www.cnblogs.com/cposture/p/4925736.html
该博文作者深入汇编,写的十分详细,感谢作者大大。
之所以挪一次,是想精简一下,并且补充一些东西。
先简单看看直接初始化和拷贝初始化的定义,然后再详细试验一下不同的拷贝初始化场景会调用哪种拷贝函数。实验环境 vs2017 已关闭编译器优化。
类的初始化分为直接初始化和拷贝初始化。
直接初始化就是在定义对象时不使用 = 号的初始化方式。调用普通构造函数。
string s1("123");
string s2(s1);
在c++11中,容器调用 emplace 成员函数创建的元素也进行直接初始化。
而拷贝初始化分很多情况,将会在以下情况发生。
需要注意的是
String s3(s1);#include <iostream>
#include <cstring>
using namespace std;
class ClassTest {
public:
ClassTest( ) {
c[0] = '\0';
cout << "ClassTest()" << endl;
}
ClassTest& operator=(const ClassTest &ct) //赋值运算符
{
strcpy(c, ct.c);
cout << "ClassTest& operator=(const ClassTest &ct)" << endl;
return *this;
}
ClassTest(ClassTest&& ct) //移动构造函数
{
cout << "ClassTest(ClassTest&& ct)" << endl;
}
ClassTest & operator=(ClassTest&& ct) //移动赋值运算符
{
strcpy(c, ct.c);
cout << "ClassTest & operator=(ClassTest&& ct)" << endl;
return *this;
}
ClassTest(const char *pc) //普通构造函数
{
strcpy(c, pc);
cout << "ClassTest (const char *pc)" << endl;
}
ClassTest(const ClassTest& ct) //拷贝构造函数
{
strcpy(c, ct.c);
cout << "ClassTest(const ClassTest& ct)" << endl;
}
private:
char c[256];
};
ClassTest f1( ) {
ClassTest c;
return c;
}
ClassTest f2( ) {
return ClassTest( );
}
void f3(ClassTest ct) {
;
}
int main( ) {
ClassTest ct1("ab");//直接初始化
ClassTest ct2 = "ab";//复制初始化
ClassTest ct3 = ct1;//复制初始化
cout << "-------3" << endl;
ClassTest ct4(ct1);//直接初始化
ClassTest ct5 = ClassTest("ab");//复制初始化
ClassTest ct6 = f1( );
cout << "-------6" << endl;
f1( );
cout << "-------1" << endl;
f2( );
cout << "-------2" << endl;
f3(ct1);
return 0;
}

下面一句一句解析这个结果。
这句和我们预期一样,直接调用相应的普通构造函数。
这句本应该是由 “ab” 实参隐式构造一个临时对象,然后通过该临时对象调用移动构造函数构造ct2。但实际上被编译器优化成1的方式。即临时对象被编译器优化掉了
4 与 5 都与我们预期相符,调用拷贝构造函数。
5 和 6 本应都是由 “ab” 实参构造一个临时对象,然后通过该临时对象调用移动构造函数构造 ct5 和ct6。但实际上被编译器优化成1的方式。即临时对象被编译器优化掉了
与 2 不同的是,这块是显式生成临时对象,如果把构造函数 explicit 声明也没有影响,而2将编译不通过。
7 和 8 结果有点出乎意料,实际上这两个过程都是相同的,区别在于调用 f1() 时,7 是将ct7的地址传给函数,而 8 是将主函数栈上的临时对象的地址传入函数内。在函数内都先为局部对象调用默认构造函数,然后将这个局部对象作为实参分别调用相应的移动构造函数构造 ct7 和临时量。
按照7 和8 的分析,这个不难看出,是将一个主函数栈上临时对象的地址传进函数内,在函数结尾处默认构造这个临时对象。
真的就是普通的拷贝构造函数。
通过上面实验过程,我们可以发现,在编译器能不用临时量就不用临时量,如2 ,5,6。
如果看不过瘾可以看看原作者的详细博文 。
原文:https://www.cnblogs.com/starrys/p/12174877.html