【问题标题】:When dose move constructor and default constructor called [duplicate]什么时候移动构造函数和默认构造函数调用[重复]
【发布时间】:2021-12-12 12:44:46
【问题描述】:

我有这个代码

class MyString {
    public:
        MyString();
        MyString(const char*);
        MyString(const String&);
        MyString(String&&) noexcept;
        ...
};

String::String()
{
    std::cout << "default construct!" <<std::endl;
}

String::String(const char* cb)
{
    std::cout << "construct with C-char!" <<std::endl;
    ...
}


String::String(const String& str)
{
    std::cout << "copy construct!" <<std::endl;
    ...
}

String::String(String&& str) noexcept
{
    std::cout << "move construct!" <<std::endl;
    ...
}

main()

MyString s1(MyString("test"));

我认为结果会是这样的:

用 C-char 构造! 调用 移动构造!

但我得到的是这样的:

用 C-char 构造!

我想的步骤

  1. MyString("test") 使用带有char* 的构造函数构造一个右值
  2. 构造 s1(arg)
  3. 由于arg是右值,s1应该由move构造函数构造 但我发现没有std::move 就不会调用移动构造函数。

为什么会这样?
如何在没有std::move()的情况下使用移动构造函数?

编译器:
Gnu C++ 9.3.0

【问题讨论】:

  • 我相信在这种情况下复制省略是强制性的。
  • @Mechap:仅从 C++17 开始。
  • 您缺少的概念是“复制省略”。见this question
  • 您的推理是正确的,您可以使用-fno-elide-constructor 标志来关闭该优化。
  • @Jarod42 仅在标准的旧版本中,它只是一个优化。您不能在 C++17 或更高版本中禁用该行为。

标签: c++ c++11 constructor


【解决方案1】:

为什么会这样?

从 C++17 开始:因为 MyString("test") 是纯右值,并且语言说在这种情况下 s1 直接从 "test" 初始化。

在 C++17 之前:因为不需要/保证会发生移动(和复制)构造函数的副作用,这允许编译器通过不创建临时对象来进行优化。这种优化称为copy elision,这是您的编译器在这里所​​做的。

如何在没有 std::move() 的情况下使用移动构造函数?

您不应该使用移动构造函数。最好不要创建多余的临时对象。您观察到的结果比您预期的要好。

如果您确实需要std::move(此处不适用),您不应该避免使用它。

因此,问题类似于“如何在不使用适当工具的情况下使管道泄漏?”。 1.您不想让管道泄漏,2.如果您出于某种原因这样做,请使用适当的工具。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-17
    • 2020-05-14
    相关资源
    最近更新 更多