将std :: unique_ptr传递给构造函数以获取所有权

kei*_*ith 5 c++ c++11

我想传递std::unique_ptr给一个类的构造函数,该类将获取所拥有的数据的所有权std::unique_ptr.

在编译器处理它们如何使其中一个更受欢迎的方法foo和方法之间是否存在任何差异bar

foo 类:

template <class T>
class foo
{
    std::unique_ptr<T> data_;

public:
    foo(std::unique_ptr<T>&& data) :
        data_{ std::forward<std::unique_ptr<T>>(data) }
    {
    }
};
Run Code Online (Sandbox Code Playgroud)

bar 类:

template <class T>
class bar
{
    std::unique_ptr<T> data_;

public:
    bar(std::unique_ptr<T> data) :
        data_{ std::move(data) }
    {
    }
};
Run Code Online (Sandbox Code Playgroud)

Ker*_* SB 6

绑定到引用需要少一点移动:

void f(std::unique_ptr<T>&& p) { g(std::move(p)); }

f(std::make_unique<T>());  // no move, g binds directly to the temporary
Run Code Online (Sandbox Code Playgroud)

绑定到对象参数需要一个实际的移动:

void f(std::unique_ptr<T> p) { g(std::move(p)); }

f(std::make_unique<T>());  // p constructed (= moved) from temporary,
                           // g binds to p
Run Code Online (Sandbox Code Playgroud)

额外的移动涉及一个指针复制,一个指向null的指针设置和一个带有条件检查的析构函数.这不是一个很大的成本,使用哪种样式的问题取决于您正在编写的代码类型:

代码越多,使用的越少,带有按值传递的简单版本就越简单.相反,您的代码库越多,您对用户的了解就越少,无论多么小,都不会产生可避免的成本.

你决定.

  • @GillBates:也许是"简化价值类别",类似的东西."Prvalues不是对象".后者准确地描述了这种变化.(由于没有任何对象,因此不会复制任何对象.)现在,也可以立即清楚为什么这与当前问题无关.并且它不会因缺少首先不存在的东西而做广告. (4认同)
  • @NathanOliver:不,那与此无关.这就是为什么我讨厌*"保证副本省略"这个词,它只会让每个人感到困惑. (2认同)