c++ - 保证复制省略的行为是否取决于用户定义的复制构造函数的存在?

标签 c++ language-lawyer c++17 copy-elision gcc8

以下代码在使用或不使用用户定义的复制构造函数时表现不同 under GCC 8.0.1 :

#include <cassert>

struct S {
    int i;
    int *p;
    S() : i(0), p(&i) {}
    // S(const S &s) : i(s.i), p(&i) {}  // #1
    // S(const S &s) : i(s.i), p(s.p) {} // #2
    // S(const S &s) = delete;           // #3
};

S make_S() {return S{};}

int main()
{
    S s = make_S();
    assert(s.p == &s.i);
}

使用任一注释的用户定义复制构造函数(即使使用#2,执行简单浅复制的构造函数),断言都不会失败,这意味着 guaranteed copy elision按预期工作。

但是,如果没有任何用户定义的复制构造函数,断言将失败,这意味着 main 函数中的对象 s 不是默认构造的。为什么会这样?此处不保证执行复制省略?

最佳答案

引用自 C++17 工作草案§15.2 临时对象第 3 段(https://timsong-cpp.github.io/cppwp/class.temporary#3):

When an object of class type X is passed to or returned from a function, if each copy constructor, move constructor, and destructor of X is either trivial or deleted, and X has at least one non-deleted copy or move constructor, implementations are permitted to create a temporary object to hold the function parameter or result object. ... [ Note: This latitude is granted to allow objects of class type to be passed to or returned from functions in registers. — end note]

在你的例子中,当我将复制和移动构造函数设置为默认值时:

S(const S &) = default;
S(S &&) = default;

GCC 和 Clang 的断言也失败了。请注意,隐式定义的构造函数是微不足道的。

关于c++ - 保证复制省略的行为是否取决于用户定义的复制构造函数的存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62408281/

相关文章:

c++ - vector 未正确填充

c++ - 我们可以有一个不在类型上但在操作上的模板吗

c++ - libcxx 中的可选 std::nullopt_t 实现

c++ - C++17 模板中的可选运算符重载

c++ - 添加 cpp 文件后体系结构 x86_64 的 undefined symbol

c++ - 这是对临时 std::string 的正确使用吗?

c - 做像 foo(x, &x) 这样的事情安全吗?

java - 三元运算符无法识别 Eclipse 中的编译错误

c++ - 引用类型和 odr-used 的模板非类型参数

c++ - 利用容器的移动语义和元素初始化