【问题标题】:How function matching works when using move and copy semantics?使用移动和复制语义时,函数匹配如何工作?
【发布时间】:2020-02-02 22:06:29
【问题描述】:

我对“移动”语义有一些含糊之处:我所读到的是,如果类已定义其自己的复制控制成员之一,则移动构造函数或赋值被隐式定义为已删除的函数。但我有这个代码:

int main()
{
    struct A {
        A() = default;
        A(const A&) { cout << "A's cpy-ctor\n"; } // this forces move ctor to be defined as a deleted function
        //A(A&&) = default;
        //A(A&&) = delete; // if uncomment this line then the line below calling std::move will cause an error(referencing a deleted function).
    };

    A a = std::move(A{}); // move not available then use copy-ctor instead


    std::cout << "\ndone\n";
}
  • 如果我取消注释第一个注释行,那么它就可以,因为我已经猜到了:使用复制构造函数而不是 move-ctor,因为它没有明确定义。

    • 但是,如果我取消注释第二条注释行,我会在调用 std::move 时收到编译时错误,抱怨删除的函数。但是为什么编译器不直接使用copy-ctor呢?

    • defulting 这个 move-ctor 是什么意思?这对函数匹配有何影响?

非常感谢!

【问题讨论】:

  • 使用复制构造函数而不是 move-ctor - 你确定吗?
  • @NutCracker:你说不?如果是,请解释一下。
  • 看看here,告诉我你看到了什么

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


【解决方案1】:

当你有一个用户声明的复制构造函数时,移动构造函数和移动赋值是未声明的,这与删除不同。

这意味着唯一有效的签名是A(A const &amp;) - 复制构造函数。

因此,当您使用右值引用(std::move 明确提供)调用构造函数时,其签名是对 const 的左值引用的复制构造函数将是最佳匹配。

但是,如果将移动构造函数定义为已删除,则会找到该签名,并且由于它是最佳匹配,编译器甚至不会尝试与复制构造函数匹配。但是,由于删除了移动构造函数,编译器说“嘿,我找到了最佳匹配,这是移动构造函数,所以我将使用那个,但它被定义为已删除,所以你不能调用它。 "

【讨论】:

  • 很好的解释。谢谢!
  • 最后一件事:将其删除会生成编译时而不是链接时?
  • 正确。尝试调用已删除的函数是编译错误。这实际上很有用,原因有几个。基本上,您是在阻止用户进行此特定调用。
  • Nit:它应该是“...当您使用右值 expression...调用构造函数时...”。表达式不能有引用类型。右值引用使左值表达式绑定到左值引用:A &amp;&amp;a; A b(a); 将调用复制构造函数,因为a 是左值。这里使用的std::move&lt;A&gt; 写成返回A&amp;&amp;,但这实际上意味着“std::move(arg) 是A 类型的右值表达式”。这两种引用都生成左值表达式,std::move 转换为右值表达式,该表达式优先绑定到右值引用,但可以绑定到const 左值表达式。
猜你喜欢
  • 2013-11-05
  • 2018-09-23
  • 1970-01-01
  • 2013-10-17
  • 1970-01-01
  • 1970-01-01
  • 2016-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多