用匿名对象,函数以值返回的局部对象初始化对象

博客讨论了C++中临时对象与拷贝构造函数的问题,指出当拷贝构造函数参数为非const引用时,编译器会阻止临时对象赋值给非const引用,导致错误。解决方案是将拷贝构造函数参数改为const引用。文章通过代码示例展示了错误情况和修正后的正确行为,并解释了编译器优化对匿名对象构造的影响。
摘要由CSDN通过智能技术生成

先看看下面这段有问题的代码:

#include<iostream>
using namespace  std;
class A
{
public:
    A(int a) :x(a) 
    { cout << "Constructor Called, and x = " << x << endl; }
    A(A& a) :x(a.x)
    {
        cout << "Copy Constructor Called, and x = " << x <<endl;
    }
    void print() { cout << "print function called, and x = " << x << endl; }
    A ReturnA() { A a(1); return a; }
    A& ReturnRef() { A a(3); return a; }
    ~A() { cout << "Deconstructor Called, and x = " << x << endl; }
private:
    int x;
};
int main()
{
    A ref = A(2);//此处会报错(1)
    ref.print();
    cout << endl;
    A refB = ref.ReturnA();//此处也会报错(2),此处仅有一次析构。
    refB.print();
    cout << endl;
    ref.ReturnA();//没有对象接收,两次析构
    cout << endl;
    A& refC = ref.ReturnRef();
    refC.print();
}

 

(1)对于(1)处的错误试图用一个A类型的匿名对象初始化一个A的对象,在新的编译器进行优化处理后,该操作只会调用普通的构造函数,但是A类的拷贝构造函数参数类型为A&(即A的非从const引用),对于匿名对象,以值返回的对象,编译器会把这两个都当做是临时对象处理,对于临时对象是不允许被修改的,编译器为了阻止这种行为,会禁止将临时对象赋值给非const的引用,所以会报错,原因就是拷贝构造函数参数类型为非const的引用。
(2)其实也是同理,用返回的临时对象去初始化一个A的对象,会调用构造和拷贝构造,但是临时对象和非const的引用(A&)参数列表是不匹配的(编译器禁止了这种行为)。
所以处理办法就是修改拷贝构造函数的传入参数类型为const 引用,即:
A(const  A& a) :x(a.x)
    {
        cout << "Copy Constructor Called, and x = " << x <<endl;
    }
这样程序就正确了,运行结果如图:

 

正如所言,编译器进行了优化,匿名对象将不会调用拷贝构造(早期编译会),只会调用普通构造函数,将匿名对象直接变为我们构造的对象。

 另外针对该程序输出可知,当以值返回局部对象时会调用拷贝构造函数,如果有对象来接收该返回值时就会用局部对象拷贝构造并赋值或者初始化它,但是如果没有对像来接收它,则仍然会调用拷贝构造函数生成临时对象但是马上销毁

这是有对象接收时(用于初始化)(一次析构:局部对象)

这是没有对象接收时(两次析构:局部对象和临时对象)

 

 对于所讲的示例,在举一个简单的例子:

 总之,常量,临时变量(包括:匿名对象,以值返回的对象)(会被编译器视作常量,即右值),是不允许赋值给非const的引用(常常会导致函数调用时实参与形参类型不符),只能赋值给const的引用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值