我注意到,如果我有以下几点:
#include <memory>
using namespace std;
class Foo
{
public:
Foo();
};
class Wobble
{
public:
void SetWibble( unique_ptr<Foo> foo )
{
this->wibble = move( foo );
}
// I like returning a ref as it gives control to
// the user of my framework over recieving a & or a copy
Foo& GetWibble()
{
return *wibble;
}
unique_ptr<Foo> wibble;
};
int _tmain(int argc, _TCHAR* argv[])
{
unique_ptr<Wobble> wobble;
unique_ptr<Foo> foo( new Foo() ); // Look here
foo->something = ...;
foo->something1 = ...;
foo->something2 = ...;
wobble->SetWibble( move( foo ) );
return 0;
}
...当我声明
foo
时,我有一个不错的Foo
对象..当我将move
的所有权归入wobble
实例时,foo在int _tmain
范围内为空。我非常喜欢这个,因为我认为这是从
int _tmain
范围中删除内存并清除指针...在我当前的上下文中,无需再摆弄任何东西...与此相反:// ...
void SetWibble( Foo& foo )
{
this->wibble = foo;
}
// ...
int _tmain(int argc, _TCHAR* argv[])
{
unique_ptr<Wobble> wobble;
Foo foo;
foo.something = ...;
foo.something1 = ...;
foo.something2 = ...;
wobble->SetWibble( foo );
return 0;
}
仍然在范围内保留对该变量的引用。
问:
最佳答案
两个示例之间的主要区别不是使用std::unique_ptr
,而是使用动态内存分配与堆栈分配。
通常最好在堆栈上分配对象。您将避免动态内存分配的开销和指针的不必要的间接调用(我看不出没有在堆栈上分配Wobble
作为开始的任何理由)。
如果您只关心范围中的变量,则可以将Foo
的创建提取到单独的函数中:
Foo createFoo() {
Foo foo;
foo.something = ...;
foo.something1 = ...;
foo.something2 = ...;
return foo;
}
int main() {
Wobble wobble;
wobble.SetWibble(createFoo());
}
另外,如果
Foo
是可移动的,则可以直接移动它,而不是移动std::unique_ptr<Foo>
:int main() {
Wobble wobble;
Foo foo;
foo.something = ...;
foo.something1 = ...;
foo.something2 = ...;
wobble.SetWibble(std::move(foo));
}
如果执行此操作,则可能要针对R值引用优化
SetWibble
。即使移动foo
没有特别的效率优势,它也至少表明该变量不再受其困扰。如果
Foo
不可移动并且复制昂贵,那么可以,则可能有理由动态分配内存。而且,是的,如果您要动态分配内存,则最好使用std::unique_ptr
管理该内存。离题:
wibble
中解引用GetWibble
。您是否可以保证wibble
不为null?可能永远不会设置它,或者可能已经将它显式设置为nullptr
也许这是调用GetWibble
的先决条件,但这是指针的额外间接调用如何增加复杂性的一个示例。 SetWibble
接受const引用会更加惯用。