【问题标题】:what does std::move(const shared_ptr reference) mean?std::move(const shared_ptr reference) 是什么意思?
【发布时间】:2020-09-01 04:02:39
【问题描述】:

以下是我正在尝试的玩具代码...我理解第一个和第二个。第一个将所有权授予_p。第二个将p 复制到_p。 但是第三个没看懂……

const shared_ptr & 中的std::move 是什么意思?谢谢。

class P { };

class A {
public:
    // first one
    A(std::shared_ptr<P> &p, int) : _p(std::move(p))
    {
        std::cout << "1st Ctor: "
                  << p.use_count() << ", " << _p.use_count() << std::endl;
    }

    // second one
    A(const std::shared_ptr<P> &p, std::string) : _p(p)
    {
        std::cout << "2nd Ctor: "
                  << p.use_count() << ", " << _p.use_count() << std::endl;
    }

    // third one
    A(const std::shared_ptr<P> &p) : _p(std::move(p))
    {
        std::cout << "3rd Ctor: "
                  << p.use_count() << ", " << _p.use_count() << std::endl;
    }

private:
    std::shared_ptr<P> _p;
};

int main()
{
    {
        std::shared_ptr<P> p = std::make_shared<P>();
        A a(p, 1);
        std::cout << "1. body: " << p.use_count() << std::endl;
    }
    std::cout << "-------------" << std::endl;
    {
        std::shared_ptr<P> p = std::make_shared<P>();
        A a(p, "2");
        std::cout << "2. body: " << p.use_count() << std::endl;
    }
    std::cout << "-------------" << std::endl;
    {
        std::shared_ptr<P> p = std::make_shared<P>();
        A a(p);
        std::cout << "3. body: " << p.use_count() << std::endl;
    }
 }

结果是:

$ ./a.out 
1st Ctor: 0, 1
1. body: 0
-------------
2nd Ctor: 2, 2
2. body: 2
-------------
3rd Ctor: 2, 2
3. body: 2

(更新:添加注释以阐明哪个是第一个,第二个等)

【问题讨论】:

  • 你可能应该更清楚你所说的“第一个”是什么意思(第一行,第一个块,第一次调用std::move?)。这同样适用于您的问题:“std::move of const shared_ptr &amp;”是什么意思?引用特定的行。
  • 在我的团队中,第 1 次、第 2 次和第 3 次在代码审查中都会被视为不好的做法。对于转移所有权A(std::shared_ptr&lt;P&gt;&amp;&amp; p)(这对于 shared_ptr 来说有点奇怪)或A(std::shared_ptr&lt;P&gt; p)(任何接收器参数的典型模式)将是表达意图的方式。
  • @Eljay,感谢您的评论。您的建议使用起来更清楚。根据您的评论,我发现const shared_ptr &amp; 在复制/移动方面似乎有些模棱两可。
  • @eric const shared_ptr &amp; 明确表示不适合搬家。

标签: c++ c++11 shared-ptr move-semantics stdmove


【解决方案1】:

std::move 只是执行转换并产生 xvalue(右值)。

当传递const std::shared_ptr&lt;P&gt; 时,其返回类型将为const std::shared_ptr&lt;P&gt;&amp;&amp;。然后对于_p(std::move(p))copy constructorstd::shared_ptr (但不是move constructor 将右值引用到non-const)将被调用,效果与第二种情况相同。

基本上移动操作倾向于对被移动的对象进行修改;它不适用于const 对象。

【讨论】:

  • 感谢您的评论。我试图继承 std::shared_ptr 并在复制 ctor 和移动 ctor 处打印。正如您所回答的,当参数为 const shared_ptr &amp; 时,调用了复制 ctor!!
【解决方案2】:

std::move 是将参数转换为右值引用的函数。函数调用是一个 xvalue 表达式。

当参数是对 const 的引用时,转换的结果是 const 的右值。如果从右值初始化为 const,将使用复制构造函数,因为移动构造函数的 non-const 的右值引用参数无法绑定到 const 的右值引用参数。

我认为 OP 还有一个隐含的问题,即 _p(std::move(p)) 可能与 _p(p) 有何不同

_p(std::move(p))const std::shared_ptr&lt;T&gt; 的情况下与_p(p) 没有区别。

理论上,如果decltype(_p) 是具有构造函数T(const T&amp;&amp;) 的类型,那么会有区别,因为该构造函数将由_p(std::move(p)) 调用,而不是由_p(p) 调用。这样的构造器将是非常规的,但在技术上是结构良好的。 std::shared_ptr 没有这样的构造函数。

【讨论】:

  • 我认为 OP 还有一个隐含的问题,即_p(std::move(p)) 可能与_p(p) 有何不同
  • @M.M 我认为没有必要提到_p(p) 也做了一个副本。我已经添加了说明。
  • 好的。我想对于具有单独的 const T&amp;&amp;T&amp;&amp; 构造函数的类来说它会有所不同
  • @M.M 确实会。你见过const T&amp;&amp;顺便使用的构造函数吗?我在非构造函数中看到过几次,但从未在构造函数中看到过。
猜你喜欢
  • 2018-06-21
  • 2017-06-11
  • 2017-02-23
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多