#include <iostream>
#include <string.h>
#include <stdlib.h>
#pragma warning(disable:4996)
using std::cout; using std::endl;
class Data
{
public:
char * name;
public:
Data() //无参构造
{
name = NULL;
}
Data(char *str)
{
name = new char[strlen(str) + 1];
strcpy(name, str);
cout << "有参构造 name = " << name << endl;
}
Data(const Data &object)//拷贝构造,手动实现深拷贝,防止同一片空间被多次释放
{
name = new char[strlen(object.name) + 1];
strcpy(name, object.name);
cout << "拷贝构造 name = " << name << endl;
}
~Data() //析构函数
{
cout << "析构函数 name = " << name << endl;
if (name != NULL)
{
delete[] name;
name = NULL;
}
}
};
Data test01()
{
Data ob1("NMMDaaa");
return ob1;
}
int main()
{
{
Data ob2 = test01();
cout << "程序执行" << endl;
}
system("PAUSE");
return 0;
}
该代码分别运行于
1、VS2015,使用默认的编译器。
2、VSCODE,使用QT安装时带的mingw530。
VS2015的运行结果:
执行了一次有参拷贝,一次拷贝,两次析构。
过程分析:
test01函数执行时,创建了新的空间给ob1,触发一次有参拷贝,在return时,先为大于4个字节的数据开辟一个临时空间,创建一个匿名对象,把return的值拷贝过去,这里触发一次拷贝构造。拷贝接收后,释放test01的空间,ob1生命结束,触发析构函数。ob2用于接收匿名对象,这个操作没有额外开辟空间,是直接鸠占鹊巢,ob2直接指向了该匿名对象的空间,因此这个过程没有触发拷贝构造。在执行后ob2生命结束,触发ob2的析构函数
VSCODE的运行结果:
执行了一次构造、一次析构。
与上面有所不同的是,ob2不经过匿名对象,直接继承ob1的空间,实际上是ob1的构造,ob2的析构
造成这个运行结果不同的是因为编译器的问题。
QT、Linux上的运行结果为第二种,其他为第一种。