【问题标题】:Using unique_ptr as a method parameter - Pros and cons使用 unique_ptr 作为方法参数 - 优点和缺点
【发布时间】:2015-07-20 16:53:36
【问题描述】:

我注意到如果我有以下情况:

#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;
}

它仍然在作用域内保留对该变量的引用。

问:

  1. 我上面说的对吗?
  2. 我想知道除了我已经指出的那些之外,使用 unique_ptr 和不使用 unique_ptr 是否有任何好处?

【问题讨论】:

  • 你可能会觉得这很有趣:herbsutter.com/2013/06/05/…
  • 这次我要好好读一下,我想我之前已经被引导到他的...
  • 您忘记了在一种情况下您使用的是堆,而在另一种情况下使用的是堆栈,选择取决于应用程序。
  • 在你的第二个例子中,我假设Wobble 中的成员变量wibble 是一个值,而不是一个引用?即Wobble::SetWibble 需要一份副本吗?

标签: c++ unique-ptr


【解决方案1】:

您的两个示例之间的主要区别不是使用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&lt;Foo&gt;

int main() {
    Wobble wobble;

    Foo foo;
    foo.something = ...;
    foo.something1 = ...;
    foo.something2 = ...;

    wobble.SetWibble(std::move(foo));
}

如果您这样做,您可能希望优化SetWibble 以获取右值引用。即使移动foo 没有特别的效率优势,它至少记录了该变量不应再被摆弄。

如果Foo 不可移动并且复制成本很高,那么可以,那么可能有理由动态分配内存。而且,是的,如果您要动态分配内存,最好使用std::unique_ptr 管理该内存。

题外话:

  • 在您的第一个示例中,请注意在 GetWibble 中取消引用 wibble。你能保证wibble 不为空吗?它可能永远不会被设置,或者它可能被显式设置为nullptr 也许这是调用GetWibble 的先决条件,但它是指针的额外间接如何增加复杂性的一个示例。
  • 在您的第二个示例中,SetWibble 采用 const 引用会更惯用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多