【问题标题】:C++11: 'decltype class instance declaration' with std::move( ) doesn't call 'move constructor.' Why?C++11:带有 std::move( ) 的“decltype 类实例声明”不调用“移动构造函数”。为什么?
【发布时间】:2018-07-16 15:15:10
【问题描述】:

我最近开始使用 c++ 并选择学习 c++11 功能。 但是 c++ 代码的运行方式有时并不那么具体。

下面是我的代码。 在decltype(std::move(sample)) sample2 = std::move(sample); 的部分,我不确定为什么这条线不调用移动构造函数。 你能解释一下为什么吗?

#include <iostream>

class AAA
{
   public:
      AAA() { std::cout << "default constructor" << std::endl; }
      AAA(const AAA& cs) { std::cout << "copy constructor" << std::endl; }
      AAA(AAA&& cs) { std::cout << "move constructor" << std::endl; }
      ~AAA() { std::cout << "destructor" << std::endl; }
};

int main(int argc, char* args[])
{
    AAA sample;
// ((right here))
    decltype(std::move(sample)) sample2 = std::move(sample); 
    return 0;
}

它是在 [ubuntu 16.04 LTS] 上用 [gcc 5.4.0] 编译的

原代码:https://ide.geeksforgeeks.org/tALvLuSNbN

【问题讨论】:

  • @user202729 很确定= std::move(sample)decltype 无关
  • 那行是AAA&amp;&amp; sample2 = std::move(sample);,它不应该比AAA&amp; sample2 = sample;更能引起构造。
  • @FrançoisAndrieux 这应该是一个答案
  • @user202729 感谢您的建议
  • @KiseongYoo 你应该知道允许临时对象绑定到const T &amp; 的语言中的一个例外,这在某些情况下可以延长临时对象的生命周期。见this question

标签: c++ c++11 move-semantics decltype stdmove


【解决方案1】:

函数std::move&lt;T&gt; 返回一个T &amp;&amp;,所以对于std::move(sample) 它返回AAA &amp;&amp;。这是一个rvalue reference,其行为很像lvalue referenceAAA &amp; 之类的类型将是一个左值引用),因为它们都是已经存在的对象的别名。

重要的是要了解std::move 本身不会 导致任何东西被移动。它只是返回一个对它给出的参数的右值引用。例如 std::move(foo); 一个人绝对什么都不做。只有当结果用于初始化或分配给一个对象时,它才变得有用。

例如auto bar = std::move(foo); 将返回一个对foo 的右值引用,并使用该引用来调用bar 的构造函数。

为了回答这个问题,由于std::move(sample) 返回一个AAA &amp;&amp;,所以有问题的行与AAA &amp;&amp; sample2 = std::move(sample); 相同。该行为实际上与AAA &amp; sample2 = sample; 相同。在这两种情况下,您都在初始化对现有对象的引用,并且不需要构造新对象。

如果您的目标是将sample 移动到新的AAA,则正确的行应该是auto sample2 = std::move(sample);,就像您对sample3 所做的那样。虽然要注意 sample3 行正在从已经移动的 sample 移动。

【讨论】:

  • 非常感谢您的详尽回答。现在我明白了幕后发生的事情。非常感谢。
【解决方案2】:

你的 sn-p 扩展为

AAA&& sample2 = std::move(sample);

将右值(std::move(sample) 的结果)绑定到右值引用(sample2)。没有构造新对象,因此没有调用这样的构造函数。

【讨论】:

  • 请注意,当表达式不指向某个具有长生命周期的对象时,它是UB。
  • 非常感谢您的回答 :) 该行确实“将右值绑定到右值引用”。我明白了。
猜你喜欢
  • 1970-01-01
  • 2015-03-21
  • 2013-01-22
  • 2023-03-16
  • 2020-11-15
  • 2018-06-06
  • 1970-01-01
  • 2015-02-14
  • 2014-12-01
相关资源
最近更新 更多