Data类
class Data
{
private:
int a;
int b;
public:
Data()
{
this->a=0;
this->b=0;
cout<<"无参构造"<<endl;
}
Data(int a,int b)
{
this->a=a;
this->b=b;
cout<<"有参构造"<<endl;
}
Data(const Data&data)
{
this->a=data.a;
this->b=data.b;
cout<<"拷贝构造"<<endl;
}
~Data()
{
cout<<"析构函数"<<endl;
}
};
例一:
Data test01()
{
Data data(10,20);//有参构造临时对象
cout<<"临时对象data地址:"<<&data<<endl;
return data;//本应该是在局部变量data被析构之前调用拷贝构造来初始化匿名对象test01(),但被Qt优化了
}
int main(int argc, char *argv[])
{
Data d1;//无参构造
d1=test01();//浅赋值
d1.showdata();
Data d2=d1;//拷贝构造
d2.showdata();
cout<<"main中d1地址:"<<&d1<<endl;
cout<<"main中d2地址:"<<&d2<<endl;
return 0;
}
运行结果:
例二:
Data test01()
{
Data data(10,20);
cout<<"临时对象data地址:"<<&data<<endl;
return data;
}
int main(int argc, char *argv[])
{
Data d1=test01();//用返回的临时对象给对象声明并赋值,不会调用拷贝构造函数而且d1的地址将和该临时对象地址一样
cout<<"main中d1地址:"<<&d1<<endl;
return 0;
}
运行结果:
这种写法临时对象空间没有在函数调用结束释放,而是对象d1的地址一样,在main函数结束时一起释放
例三:
Data& test01()
{
static Data data(10,20);//用static声明将data对象放在静态存储区,但是第二次调用这个函数,运行到这句话不会再创建新对象也不会更改data对象其中的值(哪怕10,20改成变量形式)
cout<<"临时对象data地址:"<<&data<<endl;
return data;//并且因为此时不是返回局部变量,可以将返回类型改为引用,节省时间和内存
}
int main(int argc, char *argv[])
{
Data d1=test01();//此时这句又会调用拷贝构造
cout<<"main中d1地址:"<<&d1<<endl;
return 0;
}
运行结果:
总结:
我们认为如果被赋值的对象已经被声明,那么就会调用“=”赋值操作,如果是对象未被声明则创建一个并使用拷贝构造函数(旧对象给新对象赋值)
class A;
A a;//无参构造
A b=a;//拷贝构造
A c(a);//拷贝构造
A d;
d=a;//赋值,没有重载= 时为浅赋值
但是像例二中的写法就达不到预期调用拷贝构造函数,test01()中的变量也没有正确释放。就是说函数返回值为局部对象时作为其他对象声明的赋值会出错。