保证复制省略的行为是否取决于用户定义的复制构造函数的存在? [英] Does the behavior of guaranteed copy elision depend on existence of user-defined copy constructor?

查看:109
本文介绍了保证复制省略的行为是否取决于用户定义的复制构造函数的存在?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在GCC 8.0.1下,无论有没有用户定义的复制构造函数,以下代码的行为都不同:

The following code behaves differently with or without user-defined copy constructor 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,也可以执行简单的浅表复制),断言不会失败,这意味着

With either of the commented user-defined copy constructors (even with #2, the one performing a simple shallow copy), the assertion will not fail, which means guaranteed copy elision works as expected.

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

However, without any user-defined copy constructor, the assertion fails, which means the object s in main function is not default-constructed. Why does this happen? Doesn't guaranteed copy elision perform here?

推荐答案

引用自C ++ 17工作草案§15.2临时对象第3段(

Quoting from C++17 Working Draft §15.2 Temporary Objects Paragraph 3 (https://timsong-cpp.github.io/cppwp/class.temporary#3):

当将类型X的对象传递给函数或从函数中返回时,如果X的每个副本构造函数,移动构造函数和析构函数都是微不足道的或已删除,并且X至少具有一个未删除的副本或移动构造函数,则允许实现创建一个临时对象来保存功能参数或结果对象. ... [注意:已授予此纬度,以允许将类类型的对象传递到寄存器中的函数或从其中返回. — 尾注]

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]

在您的情况下,当我将复制和移动构造函数都设为默认设置时:

In your case, when I made both copy and move constructors defaulted:

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

GCC和Clang的断言也失败了.请注意,隐式定义的构造函数很简单.

assertion failed as well with GCC and Clang. Note that implicitly-defined constructors are trivial.

这篇关于保证复制省略的行为是否取决于用户定义的复制构造函数的存在?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆