返回本地作为值/引用
这个问题来自这里的问答
我有一些疑问,我认为不能在后续评论中提出,并且不太确定我是否可以用我的疑问编辑链接的问题......因此有一个新问题。
首先,我从链接的问题中了解到,将引用返回到本地是邪恶的!
现在,考虑该问题中的相同示例,但稍作修改:
#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
现在我的疑问...
在第 2 行中, fun
getA2()
(通过 ref 返回)在破坏临时对象后返回,因此接收对象newA2
使用起来很危险。(我注释掉它的使用的原因.)那么为什么不有趣呢getA3()
会析构临时对象,即使它通过“复制”返回(请注意,getA3()
内的临时对象的析构函数不会被调用......只有newA3< /code> 对象的析构函数在
main()
结束时死亡时被调用)?我不知道那个临时文件去了哪里??现在,如果在 LINE 2 中,我将其从
A& 更改为newA2 = getA2();
到A newA2 = getA2();
,复制 ctr 在这里被调用(由于引用对象已经死亡,最终会产生段错误),但是为什么复制没有ctr 在 LINE 3 被呼叫?如何将临时状态复制到对象newA3
中,注意没有调用operator=()
?最后..这里的输出来自 gcc,但是 MSVC++2008 的工作方式有所不同吗? 即使对于LINE 3中的代码
A newA3 = getA3();
,它的行为与LINE 2相同,即,它破坏了temp回来之前!有什么线索吗?
This Question arises from a Q&A here
I have some doubts that i think cant be asked in the followup comments there, and not too sure if i could have edited the linked question with my doubts...hence a new question.
Firstly,what i learnt from the linked question is that returning ref to local is EVIL!
Now,consider the same example from that question,a bit modified though:
#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";
}
The output is as follows..
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
Now my doubts...
in LINE 2, the fun
getA2()
(which returns by ref) returns after destructing the temporary,so the recieving objectnewA2
is dangerous to use.(the reason why i have comented out its use.) so then why doesent the fungetA3()
destruct the temporary even though it returns by "copy" (Note that the temporary's destructor insidegetA3()
doesnt get called ever..onlynewA3
object's destructor gets called when it dies at the end ofmain()
)? I have no clue where does that temp go??Now if in LINE 2 i change it from
A& newA2 = getA2();
toA newA2 = getA2();
,the copy ctr gets called here(which eventually gives a segfault as the referent has died),but why doesnt the copy ctr gets called at LINE 3 ? How does the state of the temporary is getting copied into objectnewA3
,notice nooperator=()
is being called either ?Lastly.. the output here is from gcc, but does MSVC++2008 work differently??
As even for the codeA newA3 = getA3();
in LINE 3 it behaves the same as LINE 2,i.e, it destructs the temp before returning! any clues?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看来您正在从返回值优化中受益。
因为您正在将一个(尽管无效)引用复制到一个新对象中。
MSVC 和 GCC 的工作原理大致相同。避免未定义的行为(这可能比看起来更难),如果它们的工作方式不同,则编译器中存在错误。
It appears you are benefiting from Return Value Optimisation.
Because you are copying an, albeit invalid, reference into a new object.
MSVC and GCC work broadly the same. Avoid undefined behaviour (This can be harder than it may seem) and if they don't work the same way then there is a bug in the compiler.
当然,要返回的值不会被破坏,否则您将永远无法从函数返回任何内容。我相信它从本地作用域复制后会直接进入调用作用域的堆栈。
复制省略。当副本过多时(就像这里一样),编译器可以将其删除(即使它有副作用)作为一种标准规定的“优化”。这在 SO 上的许多问题中都有记录。
不清楚你想问什么。您还没有显示要比较的两个输出。
Well, of course the value to be returned is not destroyed, otherwise you'd never be able to return anything from a function. I believe it goes straight onto the calling scope's stack after copying it from the local scope.
Copy elision. When a copy is excessive (as it would be here), the compiler is allowed to elide it (even if it has side effects) as a sort of standard-prescribed "optimisation". This is documented in many, many questions on SO.
It's not clear what you're asking. You haven't shown two pieces of output to compare.