C++只调用一个构造函数
C++ only one constructor is called
我正在尝试了解右值引用。
这是我到目前为止编写的代码:
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")
是传递给第二个构造函数的临时对象,但是代码输出好像只调用了第一个构造函数。
我想这要么是编译器优化,要么我遗漏了一些关于构造函数和右值的细节。
是的,这是一个 compiler/language(见后面)优化。
与 seen here 一样,这将输出:
hello
在编译器选项中将标准从 -std=c++2a
更改为 -std=c++14
仍然只会给您 hello
,但除了标准更改之外,如果您还添加:
-fno-elide-constructors
到您应该看到您希望的选项。
但是,如果您将 C++17 或 C++2a 指定为标准,此选项将不再有效,因为在某些情况下此省略已成为强制性的,因为这些标准,您的情况就是其中之一。
您观察到的也称为copy elision,更准确地说:
Under the following circumstances, the compilers are required to omit the copy and move construction of class objects, even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:
(...)
- In the initialization of an object, when the initializer expression is a prvalue of the same class type (ignoring cv-qualification) as the variable type:
T x = T(T(f())); // only one call to default constructor of T, to initialize x
这正是你的情况。
请注意,从 C++17 开始,优化是强制性。它对于 C++11 是可选的,但似乎您的编译器无论如何都会应用它。
我正在尝试了解右值引用。 这是我到目前为止编写的代码:
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")
是传递给第二个构造函数的临时对象,但是代码输出好像只调用了第一个构造函数。
我想这要么是编译器优化,要么我遗漏了一些关于构造函数和右值的细节。
是的,这是一个 compiler/language(见后面)优化。
与 seen here 一样,这将输出:
hello
在编译器选项中将标准从 -std=c++2a
更改为 -std=c++14
仍然只会给您 hello
,但除了标准更改之外,如果您还添加:
-fno-elide-constructors
到您应该看到您希望的选项。
但是,如果您将 C++17 或 C++2a 指定为标准,此选项将不再有效,因为在某些情况下此省略已成为强制性的,因为这些标准,您的情况就是其中之一。
您观察到的也称为copy elision,更准确地说:
Under the following circumstances, the compilers are required to omit the copy and move construction of class objects, even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:
(...)
- In the initialization of an object, when the initializer expression is a prvalue of the same class type (ignoring cv-qualification) as the variable type:
T x = T(T(f())); // only one call to default constructor of T, to initialize x
这正是你的情况。
请注意,从 C++17 开始,优化是强制性。它对于 C++11 是可选的,但似乎您的编译器无论如何都会应用它。