我注意到,如果我有以下几点:

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

仍然在范围内保留对该变量的引用。

问:
  • 我上面所说的正确吗?
  • 我想知道,除了我已经指出的优点之外,使用unique_ptr而不在这里不使用unique_ptr有什么好处吗?
  • 最佳答案

    两个示例之间的主要区别不是使用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引用会更加惯用。
  • 10-07 13:35
    查看更多