我正在尝试让复制省略适用于要返回的对象的字段。
示例代码:
#include <iostream>
struct A {
bool x;
A(bool x) : x(x) {
std::cout << "A constructed" << std::endl;
}
A(const A &other) : x(other.x) {
std::cout << "A copied" << std::endl;
}
A(A &&other) : x(other.x) {
std::cout << "A moved" << std::endl;
}
A &operator=(const A &other) {
std::cout << "A reassigned" << std::endl;
if (this != &other) {
x = other.x;
}
return *this;
}
};
struct B {
A a;
B(const A &a) : a(a) {
std::cout << "B constructed" << std::endl;
}
B(const B &other) : a(other.a) {
std::cout << "B copied" << std::endl;
}
B(B &&other) : a(other.a) {
std::cout << "B moved" << std::endl;
}
B &operator=(const B &other) {
std::cout << "B reassigned" << std::endl;
if (this != &other) {
a = other.a;
}
return *this;
}
};
B foo() {
return B{A{true}};
}
int main() {
B b = foo();
std::cout << b.a.x << std::endl;
}
我编译:
g++ -std=c++17 test.cpp -o test.exe
输出:
A constructed
A copied
B constructed
1
B 是就地构建的。为什么A不是?我至少希望它是移动构造的,但它是被复制的。
有没有办法在要返回的 B 内部就地构造 A?怎么办?
最佳答案
从 A
构造 B
涉及复制 A
- 它在您的代码中是这样说的。这与函数返回中的复制省略无关,所有这些都发生在 B 的(最终)构造中。标准中没有任何内容允许删除(如“打破假设规则”)成员初始化列表中的复制构造。请参阅[class.copy.elision]
对于少数可能会违反假设规则的情况。
换句话说:创建 B b{A{true}};
时,您会得到完全相同的输出。函数返回值同样好,但并没有更好。
如果您希望移动 A
而不是复制,则需要一个构造函数 B(A&&)
(然后移动构造 a
> 成员(member))。
关于C++ 字段的复制省略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59756657/