C ++&符号从函数接收对象

时间:2012-04-10 22:31:20

标签: c++ oop object

我有一个包含普通构造函数和复制构造函数的类的以下简单代码

class largeObj
{
public:
    largeObj()
    {
        printf("\nNormal constructor\n");
    }

    largeObj(const largeObj& mv)
    {
        printf("\nCopy constructor\n");
    }

    ~largeObj()
    {
        printf("\nDestroying..\n");
    }

    void tryme()
    {
        printf("\nHi :)\n");
    }

};

largeObj iReturnLargeObjects()
{
    largeObj md;


    return md;
}


int main()
{

    largeObj mdd = iReturnLargeObjects();

    mdd.tryme();

    return 0;
}

输出

  

普通构造函数

     

复制构造函数

     

销毁..

     

嗨:)

我明白了。

但是,如果我替换以下行

largeObj mdd = iReturnLargeObjects();

largeObj& mdd = iReturnLargeObjects();

输出是一样的,为什么呢?

我的意思是:第一种情况下不应该有另一个副本(没有&)?这两条线之间有什么区别,为什么它们表现相同?

2 个答案:

答案 0 :(得分:4)

largeObj& mdd = iReturnLargeObjects();

您不能将可变左值引用绑定到右值。这是非法的C ++,只允许某些特定的编译器扩展。但是,问题的语义没有改变,即使这个引用是const因此赋值是合法的。

您的输出没有区别的原因是因为编译器优化称为RVO。这种优化(在C ++标准中明确允许)允许编译器在某些限制内跳过构造它确定不必要的对象 - 即使这样做会改变程序的语义,这使得它成为一种非常不寻常的优化。 p>

底线是:不要在副本/移动构造函数和析构函数中放置副作用,因为编译器可以消除它们,即使程序的正确性取决于它们被调用。

答案 1 :(得分:0)

你使用了什么编译器,我愿意打赌这是有效的,因为你使用的任何编译器都没有在返回后将未使用的堆栈变量归零,你没有得到seg错误,因为它仍然是你的堆栈。基本上md留在堆栈上,你在技术上仍然可以解决。两者之间的区别是

  

largeObj md;

是一个完整接收变量的变量。

  

largeObj&安培; mdd = iReturnLargeObjects();

是对由于惰性编译器仍然存在而导致的变量的引用。