【问题标题】:why move constructor being used instead of copy?为什么使用移动构造函数而不是复制?
【发布时间】:2021-06-29 03:01:11
【问题描述】:

为什么调用移动构造函数而不是复制构造函数?当我删除移动构造函数时,就会调用复制构造函数。

使用:-fno-elide-constructors 避免复制省略

#include <iostream>
class test
{
public:
    int x;
    char y;
    bool t;
    test()
    {
        std::cout << " constructed" << std::endl;
    }
    test(test &&temp)
    {
        std::cout << "move constructor" << std::endl;
    }
    test(const test &temp)
    {
        std::cout << "copy constructor" << std::endl;
    }
    template <typename... Args>
    static test create(Args... x)
    {
        test b(x...);
        return b;
    }
};
int main()
{
    test z = test::create();
    test v = test();
}

输出:

 constructed
move constructor
move constructor
 constructed
move constructor

上述情况可能是什么原因?

【问题讨论】:

  • 为什么这让您感到惊讶?分配时会自动移动临时值
  • 这很有趣。你用的是什么编译器?我本来希望复制省略可以工作,所以唯一的输出应该是“构造的”。
  • 我试过了:godbolt.org/z/8EcbbTKf5 gcc 和 clang 只打印 constructed constructed,即使是几年前的版本。
  • 您期望什么行为?您希望在哪里调用复制构造函数,为什么?对我来说,这里唯一有趣的是你的问题的标题不是“为什么使用移动构造函数而不是省略?”。
  • @MariusBancila 我明确使用了“-fno-elide-constructors”

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


【解决方案1】:

我认为这是基本的移动语义。将临时变量分配给非临时变量时,只要存在移动运算符(默认或指定使用),就会使用它。查看 Klaus Igelberger 的演讲。我认为是 cppcon 2019。 -道歉。我的意思是回复不回复

【讨论】:

    【解决方案2】:

    来自https://en.cppreference.com/w/cpp/language/return#Automatic_move_from_local_variables_and_parameters,这主要是NRVO的后备:

    然后执行两次重载决议以选择用于初始化返回值 [..] 的构造函数:

    • 首先好像表达式是一个右值表达式(因此它可以选择移动构造函数),然后 如果第一个重载决议失败或

    [...]

    所以return b; 在没有省略复制/移动时会执行移动构造函数(如果可用)。

    对于test v = test();,test() 是一个右值,在 C++17 之前,将使用移动构造函数(如果未省略)(如果可用)。

    在 C++17 中,甚至不会创建该临时对象,这将避免使用移动构造函数(主要与复制/移动省略版本一样,只是复制/移动不必是可访问的)。

    如果你移除你的移动构造器,因为你提供了一个复制器,移动器不会生成,只有复制构造器可用,并用来代替移动构造器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-10
      • 1970-01-01
      • 2013-04-25
      • 1970-01-01
      • 2012-04-29
      • 2019-11-07
      • 1970-01-01
      相关资源
      最近更新 更多