返回本地值作为值/引用

时间:2012-01-26 10:43:03

标签: c++ reference return-value local

此问题来自Q& A here

我有一些疑问,我认为不能在那里的后续评论中被问到,并且不太确定我是否可以用疑惑编辑链接的问题......因此是一个新问题。

首先,我从相关问题中学到的是,将ref返回到本地就是EVIL!

现在,请考虑该问题中的相同示例,但稍微修改一下:

#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
class A
{
    public:
        int x;
        string s;
        A(int xx,string ss):x(xx),s(ss)
    {
        cout<<"A::A()"<<x<<","<<s<<"\n";
    }
        A(const A& that)
        {
            cout<<"cpy ctr\n";
            x=that.x;
            s=that.s;
        }
        A& operator=(const A& that)
        {
            cout<<"operator=\n";
        }
        ~A()
        {
            cout<<"~A()"<<s<<"\n";
        }
};

const A& getA1()
{
    A a(1,"A1");
    cout<<"returning from A1\n";
    return a;
}

A& getA2()
{
    A a(2,"A2");
    cout<<"returning from A2\n";
    return a;
}

A getA3()
{
    A a(3,"A3");
    cout<<"returning from A3\n";
    return a;
}

int main()
{ 
    A &newA2 = getA2();       //.....................LINE 2
    cout<<"returned from A2\n";
    cout<<"-----------------------------\n";
    A newA3 = getA3();       //......................LINE 3
    //A const  newConstA3 = getA3 ();
    cout<<"returned from A3\n";
    cout<<"-----------------------------\n";
    //cout<<"newA2="<<newA2.x<<","<<newA2.s<<"\n";
    cout<<"newA3="<<newA3.x<<","<<newA3.s<<"\n";

}

输出如下..

A::A()2,A2
returning from A2
~A()A2
returned from A2
-----------------------------
A::A()3,A3
returning from A3
returned from A3
-----------------------------
newA3=3,A3
~A()A3

现在我怀疑......

    LINE 2
  1. ,在破坏临时值后,有趣getA2()(由ref返回)返回,因此接收对象newA2使用起来很危险。 (之所以我已经注释掉了它的用法。)那么为什么即使它通过“复制”返回,也为什么要执行有趣的getA3()破坏临时(注意getA3()内的临时析构函数不会被调用..only newA3对象的析构函数在main()}结束时被调用?我不知道那个临时去哪儿了?

  2. 现在,如果在 LINE 2 中我将其从A& newA2 = getA2();更改为A newA2 = getA2();,则会在此处调用复制ctr(最终会产生一个段落错误,因为指示对象具有死了),但为什么复制ctr在 LINE 3 被调用?如何将临时状态复制到对象newA3中,注意没有调用operator=()

  3. 最后..这里的输出来自gcc,但MSVC ++ 2008的工作方式不同吗? 即使 LINE 3 中的代码A newA3 = getA3();,它的行为与 LINE 2 相同,即在返回之前它会破坏临时值!任何线索?

2 个答案:

答案 0 :(得分:2)

  1. 您似乎从Return Value Optimisation中受益。

  2. 因为您正在将一个(尽管是无效的)引用复制到一个新对象中。

  3. MSVC和GCC大致相同。避免未定义的行为(这可能比它看起来更难),如果它们的工作方式不同,那么编译器就会出现错误。

答案 1 :(得分:0)

  1. 当然,要返回的值不会被销毁,否则您将永远无法从函数返回任何内容。我相信它在从本地范围复制后直接进入调用范围的堆栈。

  2. 复制elision。当副本过多时(就像在这里一样),编译器可以将它(即使它有副作用)作为一种标准规定的“优化”。关于SO的许多问题都记录了这一点。

  3. 目前尚不清楚你在问什么。您没有显示两个要比较的输出。

相关问题