c++中的匿名对象
大纲
1)什么是匿名对象(也称临时对象)
2)产生匿名对象的三种情况
1.产生匿名对象的三种情况:
1)以值的方式给函数传参;
Cat(); —> 生成了一个匿名对象,执行完Cat( )代码后,此匿名对象就此消失。这就是匿名对象的生命周期。
Cat cc = Cat(); —>首先生成了一个匿名对象,然后将此匿名对象变为了cc对象,其生命周期就变成了cc对象的生命周期。
2)类型转换;
3)函数需要返回一个对象时;return temp;
2.匿名对象的生命周期
注意:匿名对象的生命周期(很重要!!!)
例子1:
<span style="color:#333333"><span style="background-color:#f9f5e9"><code class="language-cpp">class A
{
public:
A(int s)
{
i = s;
}
void myshow()
{
cout<<i<<endl;
}
private:
int i;
};
void playstage()
{
cout<<A(10).myshow()<<endl;//调用匿名对象
A a = 11;//此处发生隐身转换。。。。相当于 A a = A(11); 此处的A(11)就是一个匿名对象
A b = A(12);//当匿名对象有等待初始化的对象接的时候,只调用一次构造和析构函数
A c;//调用一次构造函数
c = A(13);//此处为赋值。。。。。此处的匿名对象会调用一次构造函数
}
void main()
{
playstage();
system("pause");
}
</code></span></span>
例2:
<span style="color:#333333"><span style="background-color:#f9f5e9"><code class="language-cpp">class Cat
{
public:
Cat()
{
cout<<"Cat类 无参构造函数"<<endl;
}
Cat(Cat& obj)
{
cout<<"Cat类 拷贝构造函数"<<endl;
}
~Cat()
{
cout<<"Cat类 析构函数 "<<endl;
}
};
void playStage() //一个舞台,展示对象的生命周期
{
Cat(); /*在执行此代码时,利用无参构造函数生成了一个匿名Cat类对象;执行完此行代码,
因为外部没有接此匿名对象的变量,此匿名又被析构了*/
Cat cc = Cat(); /*在执行此代码时,利用无参构造函数生成了一个匿名Cat类对象;然后将此匿名变 成了cc这个实例对象*/
}
int main()
{
playStage();
system("pause");
return 0;
}
</code></span></span>
输出:
1.Cat类 无参构造函数
2.Cat类 析构函数
3.Cat类 无参构造函数
4.Cat类 析构函数
说明:
1、在执行playStage( )函数中的Cat( )时,生成了一个匿名对象,执行完Cat( )代码后,此匿名对象就此消失。这就是匿名对象的生命周期。
2、在执行playStage( )函数中Cat cc = Cat();时,首先生成了一个匿名对象,因为外部有cc对象在等待被实例化,然后将此匿名对象变为了cc对象,其生命周期就变成了cc对象的生命周期。
总结:
如果生成的匿名对象在外部有对象等待被其实例化,此匿名对象的生命周期就变成了外部对象的生命周期;如果生成的匿名对象在外面没有对象等待被其实例化,此匿名对象将会生成之后,立马被析构。
3.匿名对象产生的三种场景
<span style="color:#333333"><span style="background-color:#f9f5e9"><code class="language-cpp">//匿名对象产生的三种场景
#include<iostream>
using namespace std;
class Point{
public:
Point(int a,int b){
cout << "有参构造函数被调用了1" << endl;
this->x = a;
this->y = b;
}
Point(Point &a1){
cout << "拷贝构造函数被调用了2" << endl;
this->x = a1.x;
this->y = a1.y;
}
~Point(){
cout << "析构函数被调用了3" << endl;
cout << "x=" << x << endl;
cout << "y=" << y << endl;
}
Point Protset(int a){
this->x = a;
return *this;
//执行 return *this; 会产生一个匿名对象,作为返回值
//强调:如果返回值是引用,则不会产生匿名对象
}
Point Protset2(int a){
Point temp(a, a);
return temp;
//执行 return temp;会先产生一个匿名对象,执行拷贝构造函数,作为返回值,
//然后释放临时对象temp
}
//总结:函数返回值为一个对象(非引用)的时候会产生一个匿名对象,匿名对象根据主函数的操作决定生命周期
Point& Protset3(int a){
Point temp(a, a);
return temp;
//执行 return temp;不会产生匿名对象,而是会将temp的地址先赋值到引用中,
//在释放temp的内存,此时Point&得到是一个脏数据
}
void PrintfA()const{
cout << "x="<<x << endl;
cout << "y=" << y << endl;
}
private:
int x;
int y;
};
void ProtectA(){
//生成一个匿名对象,因为用来初始化另一个同类型的对象,这个匿名对象会直接转换成新的对象,
//减少资源消耗
Point p1 = Point(1,1);
/*Point p2(2, 2);
p2 = p1.Protset(3);
p2.PrintfA();*/
//观察发现p2打印出正确数据,因此得出结论p1.Protset(3);返回来一个匿名对象,
//但是这个匿名对象执行完"="之后,才会被释放
Point p4(5, 5);
p4=p1.Protset2(4);
p4.PrintfA();
}
void main(){
ProtectA();
system("pause");
}</code></span></span>