您可以在函数调用中直接使用make_unique吗?

时间:2019-05-07 17:50:59

标签: c++ c++14 smart-pointers

我正在尝试更新一些传递新对象的代码。目标是使用智能指针对其进行管理。熬下来,看起来很像这样:

class X
{
    shared_ptr<Y> yptr;

    X() : yptr(Y::create(new Z())){}
};

class Y
{
    Z* zptr;
    static shared_ptr<Y> create(Z* zp)
    {
        if(!zp) return nullptr;
        else return shared_ptr<Y>(new Y(zp));
    }

    Y(Z* zp) : zptr(zp){}
}

到目前为止,这似乎可行:

class X
{
    shared_ptr<Y> yptr;

    X() : yptr(Y::create(  std::move(  std::make_unique<Z>(Z())  )  )){}
};

class Y
{
    unique_ptr<Z> zptr;
    static shared_ptr<Y> create(unique_ptr<Z> zp)
    {
        if(!zp) return nullptr;
        else return shared_ptr<Y>(new Y(std::move(zp)));
    }

    Y(unique_ptr<Z> zp) : zptr(std::move(zp)){}
}

我的问题是,第一个std :: move()(在make_unique附近)是否必要? Visual Studio似乎都不介意。在开始对性能更为关键的其他地方进行类似更改之前,我希望有一个准确的了解。

3 个答案:

答案 0 :(得分:0)

简短答案:

函数调用std::make_unique<Z>()返回一个右值,因此,如果将其直接传递到另一个函数中,则无需将其包装在std::move()中。

答案 1 :(得分:0)

  

我的问题是,第一个std :: move()(在make_unique附近)是否必要?

如果您指的是这一行:

X() : yptr(Y::create(  std::move(  std::make_unique<Z>(Z())  )  )){}

然后不,因为std::make_unique<Z>返回已经是prvalue的临时值,所以完全没有必要。您可以执行以下操作:

auto ptr = std::move( std::move( std::move( std::make_unique<Z>() ) ) );

代替

auto ptr = std::make_unique<Z>();

但是所有moves都是不必要的,事实已经清楚地表明了这一点。

答案 2 :(得分:0)

是的!无需make_unique左右移动。

std::move用于将左值引用&(指向现有对象)转换为右值引用&&(表示临时值,或可以从中移出。)

如果您将unique_ptr分配给命名变量,那么如果您想转移其所有权,则确实需要从其std::move(通常;请参见下文)。您不能直接将r值引用绑定到变量。

由表达式或函数调用返回的值(例如unique_ptr返回的make_shared)是临时的,因此它自然可以绑定到r值表达式并从中移出隐式地。

请注意,在某些特殊情况下,您不需要使用std::move

  • 如果您有一个命名变量,其类型是一个r值引用,则要做,需要std::move,以避免通过复制传递它:

    MyClass(std::string&& s) : m_mystring(s) {} 复制-构造m_mystring

    MyClass(std::string&& s) : m_mystring(std::move(s)) {}移动结构m_mystring

    通常,带名称的变量不会隐式地移出。

  • 如果要通过函数从值返回局部变量,则该对象可能会自动从所谓的Named Return Value Optimization中移出。这样可以很好地提高按值返回的速度。在实践中,您无需考虑这一点,只需注意return std::move(whatever);几乎总是错误的。

相关问题