【问题标题】:C++ only one constructor is called [duplicate]C ++只有一个构造函数被称为[重复]
【发布时间】:2021-07-29 18:55:17
【问题描述】:

我正在尝试理解右值引用。 这是我目前写的代码:

class A {
public:
    A(const char* str) {
        std::cout << str;
    }

    A(A&& other) {
        std::cout << "other";
    }
};

int main() {
    A m(A(A(A("hello"))));
}

输出只有"hello",搞得我一头雾水。

由于A("hello")是传递给第二个构造函数的临时对象,但是代码输出好像只调用了第一个构造函数。

我猜这要么是编译器优化,要么我错过了一些关于构造函数和右值的细节。

【问题讨论】:

  • 是的,这是一种优化。

标签: c++ c++11 constructor rvalue-reference


【解决方案1】:

你观察到的也称为copy elision,更准确地说:

在以下情况下,编译器需要省略类对象的复制和移动构造,即使复制/移动构造函数和析构函数具有可观察到的副作用。对象直接构建到存储中,否则它们将被复制/移动到。复制/移动构造函数不需要存在或可访问:

(...)

  • 在对象的初始化中,当初始化表达式是与变量类型相同的类类型(忽略 cv-qualification)的纯右值时:

T x = T(T(f())); // 只调用一次 T 的默认构造函数,初始化 x

这正是你的情况。

请注意,对于 C++17 及更高版本,优化是强制。它对于 C++11 是可选的,但您的编译器似乎无论如何都会应用它。

【讨论】:

    【解决方案2】:

    是的,这是一种编译器/语言(见后文)优化。

    可以是seen here,这将输出:

    hello
    

    在编译器选项中将标准从 -std=c++2a 更改为 -std=c++14 仍然只会给您 hello,但除了标准更改之外,如果您还添加: -fno-elide-constructors 到您应该看到的选项。

    但是,如果您将 C++17 或 C++2a 指定为标准,则此选项将不再起作用,因为在某些情况下,此省略已成为强制性的,因为这些标准是您的情况之一。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-26
      • 1970-01-01
      • 1970-01-01
      • 2017-01-05
      • 2014-01-19
      相关资源
      最近更新 更多