获取此代码:
struct Bar { //has non-default copy-constructor
Bar() = default;
Bar(const Bar&) {}
};
struct LargeObject { //has default copy-constructor
std::array<char, 1000> m_chars;
};
struct Foo {
Bar m_bar;
LargeObject m_obj;
};
Foo func() { Foo f; return f; }
当用户指定复制构造函数时,编译器无法删除副本。当类的成员具有非默认复制构造函数时该怎么办?在此代码中,当从
f
返回 func
时,编译器是否可以删除 m_obj
的副本,还是必须复制所有内容?
你的问题是基于一个错误的前提。编译器完全有权删除这样的副本,无论类本身或其成员之一是否具有非默认复制(或移动)构造函数。自 C++11 以来引入的复制省略规则的好处是允许这种优化,即使它违反了 as-if 规则。 如果做不到这一点,复制省略就没有那么有用了;即使只有一个智能指针(具有自定义复制和移动构造函数)的类也没有资格使用 RVO,除非编译器可以肯定地证明没有违反 as-if 规则。
在您的特定场景中,编译器可以在启用优化的情况下(这不是强制性的,因为您依赖于非强制性 NRVO,而不是简单 RVO 的 C++17 保证复制省略)通过以下方式实现
func
直接将
Foo
对象构建到调用者提供的存储中,而不使用必须移动/复制回调用者的单独 Foo f
。