首页 > 解决方案 > C++ 复制省略字段

问题描述

我试图让复制省略适用于要返回的对象的字段。

示例代码:

#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?如何?

标签: c++c++17in-placecopy-elision

解决方案


B从a 构造 aA涉及复制A- 它在您的代码中如此说明。这与函数返回中的复制省略无关,所有这些都发生在B. 标准中的任何内容都不允许删除(如“打破 as-if 规则”)成员初始化列表中的复制构造。查看[class.copy.elision]少数情况下可能会违反 as-if 规则。

换句话说:你在创建时得到完全相同的输出B b{A{true}};。函数返回完全一样好,但不是更好。

如果要A移动而不是复制,则需要一个构造函数B(A&&)(然后移动构造该a成员)。


推荐阅读