bra*_*ter 19 c++ memory return-value pass-by-reference
我现在真的很困惑如何以及使用哪种方法从函数返回对象.我想要针对给定要求的解决方案提供一些反馈.
场景A:返回的对象将存储在一个变量中,该变量在其生命周期内无需修改.从而,
const Foo SomeClass::GetFoo() {
return Foo();
}
Run Code Online (Sandbox Code Playgroud)
调用为:
someMethod() {
const Foo& l_Foo = someClassPInstance->GetFoo();
//...
}
Run Code Online (Sandbox Code Playgroud)
Scneraio B:返回的对象将存储在一个变量中,该变量将在其生命周期内被修改.从而,
void SomeClass::GetFoo(Foo& a_Foo_ref) {
a_Foo_ref = Foo();
}
Run Code Online (Sandbox Code Playgroud)
调用为:
someMethod() {
Foo l_Foo;
someClassPInstance->GetFoo(l_Foo);
//...
}
Run Code Online (Sandbox Code Playgroud)
我在这里有一个问题:让我们说Foo不能有默认的构造函数.那么在这种情况下你会怎么处理呢,因为我们不能再写这个了:
Foo l_Foo
Run Code Online (Sandbox Code Playgroud)
场景C:
Foo SomeClass::GetFoo() {
return Foo();
}
Run Code Online (Sandbox Code Playgroud)
调用为:
someMethod() {
Foo l_Foo = someClassPInstance->GetFoo();
//...
}
Run Code Online (Sandbox Code Playgroud)
我认为这不是推荐的方法,因为它会导致构建额外的临时工.
你怎么看 ?另外,您是否建议使用更好的方法来处理此问题?
pet*_*hen 16
首先,让我们来看看这里发挥作用的事情:
(a)延长临时用于初始化参考的寿命 - 我在本出版物中由Andrei Anexandrescu 了解到它.再次,它感觉很奇怪,但很有用:
class Foo { ... }
Foo GetFoo() { return Foo(); } // returning temporary
void UseGetFoo()
{
Foo const & foo = GetFoo();
// ... rock'n'roll ...
foo.StillHere();
}
Run Code Online (Sandbox Code Playgroud)
规则说,当使用临时初始化引用时,临时的生命周期将延长,直到引用超出范围.(这个回复引用了佳能)
(b)返回值优化 - (维基百科) - 本地的两个副本 - >返回值 - >本地可能在某些情况下被省略.这是一个令人惊讶的规则,因为它允许编译器更改可观察的行为,但很有用.
你有它.C++ - 奇怪但有用.
所以看看你的场景
场景A:您返回一个临时的,并将其绑定到引用 - 临时的生命周期延长到l_Foo的生命周期.
请注意,如果GetFoo返回引用而不是临时引用,则无效.
场景B:工作,除了它强制构造 - 构造 - 复制周期(可能比单个构造更昂贵),以及您提到的关于需要默认构造函数的问题.
我不会使用该模式来创建对象 - 仅用于改变现有对象.
场景C:编译器可以省略临时副本(从RVO规则开始).遗憾的是没有保证 - 但现代编译器确实实现了RVO.
C++ 0x中的Rvalue引用允许Foo实现资源窃取构造函数,不仅可以保证副本的抑制,而且在其他场景中也可以派上用场.
(我怀疑有一个编译器实现了右值引用而不是RVO.但是有些情况下RVO无法启动.)
像这样的问题需要提到智能指针,例如shared_ptr和unique_ptr(后者是"安全的" auto_ptr).它们也在C++ 0x中.它们为创建对象的函数提供了另一种模式.