【问题标题】:Why `copy constructor` is used while `move constructor` has been removed?为什么在移除“移动构造函数”时使用“复制构造函数”?
【发布时间】:2020-05-30 04:21:30
【问题描述】:

作为主题,相关代码为:

#include <iostream>     

class ABC     
{  public:  
    ABC() 
    {
        std::cout<< "default construction" << std::endl;
    }

    ABC(const ABC& a) 
    {
        std::cout << "copy construction" << std::endl;
    } 

    ABC(const ABC&& a) 
    {
        std::cout << "move construction" << std::endl;
    }
};                         

int main()   
{  
   ABC c1 = ABC();  

   return 0;  
}

使用 -fno-elide-constructors -std=c++11 输出

default construction
move construction

如果我删除上面的移动构造函数,那么输出是:

default construction
copy construction

为什么 copy construction 可以在 move constructor 被删除时使用?你看,如果有用户定义的 move constructor,编译器更喜欢使用 move constructor

根据一些文档,编译器提供了默认的move constructor。**那么为什么编译器不使用默认的move constructor? 我是 C++ 的新手。如果能在这个问题上得到一些帮助,我将不胜感激。

【问题讨论】:

  • ABC(const ABC&amp;&amp;) 不是移动 ctor。删除 const:ABC(ABC&amp;&amp;).
  • @谢谢。你能详细解释一下吗?我有点困惑,因为这段代码(删除关键字const)[godbolt.org/z/YAwdMo]确实可以编译。
  • 看来我错了。 Cppreference 说 T(const T&amp;&amp;) 确实 算作移动 ctor。反正。从阅读 cppreference: rule of five 开始,然后点击链接到专门的 ctor/assignment 页面。
  • @besc 你认为T(T&amp;&amp;)(没有关键字const)算作移动ctor吗?

标签: c++ c++11 constructor copy-constructor move-semantics


【解决方案1】:

根据一些文档,编译器提供默认的move constructor

让我们看一些文档。以下来自cppreference.com

如果 [conditions] 则编译器会将移动构造函数声明为其类的非显式内联公共成员,并带有签名 T::T(T&amp;&amp;)

你是对的。编译器确实在正确的条件下提供了一个默认的移动构造函数。 但是,这些条件很重要。 您似乎知道的第一个条件:不能有用户定义的移动构造函数。所以只剩下这个条件列表:

  • 没有用户声明的复制构造函数;
  • 没有用户声明的复制赋值运算符;
  • 没有用户声明的移动赋值运算符;
  • 没有用户声明的析构函数;

然后就可以了。您的用户定义的复制构造函数阻止编译器提供默认的移动构造函数。因此没有可使用的移动构造函数。

【讨论】:

  • 感谢您的澄清。那为什么copy construction 可以使用而move constructor 已被删除?你看,如果有用户定义move constructor,编译器更喜欢使用@987654328 @.
  • 如果move ctor不可用,则通过普通函数匹配选择copy ctorconst ABC&amp; 可以绑定到使用ABC() 创建的临时。在存在move ctor 的情况下,ABC&amp;&amp; 是更好的匹配,因为不需要const conversion。 @sunshilong369
  • @User10482 感谢您的澄清。C++ 标准授予它(const ABC& 可以绑定到使用 ABC() 创建的临时值)吗?还有一个问题,为什么编译器在ABC(const ABC&amp;) 时会抱怨替换为 `ABC(ABC&)` ?
  • @sunshilong369 是的,编译器更喜欢使用移动构造函数而不是复制构造函数。但是,它更倾向于使用存在的东西而不是不存在的东西。复制构造函数确实适合这种用途,只是不如移动构造函数。
  • @sunshilong369 您的构造从一个临时的ABC 对象开始,然后将其转移(移动或复制)到另一个对象。也就是说,移动或复制构造函数的参数是一个临时对象。所以询问ABC(ABC&amp;) 接近于询问How come a non-const reference cannot bind to a temporary object?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-25
  • 1970-01-01
相关资源
最近更新 更多