【问题标题】:Should shared_ptr constructor arguments be passed by valueshared_ptr 构造函数参数是否应该按值传递
【发布时间】:2019-01-04 09:15:47
【问题描述】:

当我将shared_ptr 传递给将参数复制到成员shared_ptr 的构造函数时,该参数是否应该按值传递?

例子:

struct MyClass {
    MyClass(std::shared_ptr<MyDependency> dep) 
        : dep(dep)
    {}

    std::shared_ptr<MyDependency> dep;
};

如果使用临时 (MyClass(std::make_shared&lt;...&gt;())) 构造,编译器应该移动参数(一次还是两次?)。

编译器是否能够“自动”将dep 移动到dep, 还是我应该使用: dep(std::move(dep))

如果使用左值构造,则该值将被复制(最少一次)。

另一方面,通过 const-ref 传递 shared_ptr 将始终复制指针。

那么构造函数参数如果直接复制到成员中,是否应该传值呢?

编辑:参数/成员必须是shared_ptr

【问题讨论】:

标签: c++ constructor pass-by-reference move pass-by-value


【解决方案1】:

shared_ptr 构造函数参数是否应该按值传递

如果您打算共享所有权,即您想保留一份副本:是的,按值传递是首选方式。

如果使用临时构造...编译器应该移动参数(一次还是两次?)。

首先参数被移动构造,然后成员被初始化(见下文)。在某些情况下,论证的结构可能会被省略。

我应该使用: dep(std::move(dep))

是的,你应该这样做。参数有一个名字,所以它是一个左值。要移动构造成员,您需要有一个右值。

【讨论】:

  • 好的,所以我们最终可能会移动两次?
  • @Aconcagua 是的。甚至可能两次。我开始怀疑省略的可能性。
  • 嗯,我想得越多,复制省略应该适用于MyClass(std::make_shared()),不过,另一件事是MyClass(std::move(somePtr))
  • 目前总结:三种情况:按值:传左值:复制+移动。传递 r 值:移动 + 移动,在可能发生复制省略的情况下:仅移动一次。通过引用:传递左值:复制;传递 r 值:复制(两种情况)。
  • @johannes 正确。使用共享所有权,甚至仅使用动态分配的开销是如此之高,以至于我不会关心额外移动的微不足道的成本。请注意,当需要处理多个成员时,重载将变得难以忍受。
【解决方案2】:

我个人的方法是使用两个构造函数:

struct MyClass
{
    MyClass(std::shared_ptr<MyDependency> const& dep) 
        : dep(dep)
    {}
    MyClass(std::shared_ptr<MyDependency>&& dep) 
        : dep(std::move(dep))
    {}

    std::shared_ptr<MyDependency> dep;
};

传递的左值,外部指针保留所有权,只复制一次,右值仍然只是引用,因此只移动一次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 2012-01-17
    • 2012-01-21
    • 2021-04-05
    • 2015-01-13
    相关资源
    最近更新 更多