编译器可以删除特定数据成员的副本吗?

问题描述 投票:0回答:1

获取此代码:

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++ move-semantics
1个回答
0
投票

你的问题是基于一个错误的前提。编译器完全有权删除这样的副本,无论类本身或其成员之一是否具有非默认复制(或移动)构造函数。自 C++11 以来引入的复制省略规则的好处是允许这种优化,即使它违反了 as-if 规则。 如果做不到这一点,复制省略就没有那么有用了;即使只有一个智能指针(具有自定义复制和移动构造函数)的类也没有资格使用 RVO,除非编译器可以肯定地证明没有违反 as-if 规则。

在您的特定场景中,编译器可以在启用优化的情况下(这不是强制性的,因为您依赖于非强制性 NRVO,而不是简单 RVO 的 C++17 保证复制省略)通过以下方式实现

func

直接将

Foo
对象构建到调用者提供的存储中,而不使用必须移动/复制回调用者的单独
Foo f
    

© www.soinside.com 2019 - 2024. All rights reserved.