为什么 std::atomic 从 C++17 开始编译,即使删除了复制构造函数?

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

我有一个简单的代码:

#include <atomic>

int main()
{
    std::atomic<int> a = 0;
}

此代码在使用 -std=c++17 的 GCC 11.1.0 上可以正常编译,但使用 -std=c++14 和 -std=c++11 时会失败。

使用已删除的函数 std::atomic::atomic(const std::atomic&)

这是为什么呢?在 C++17 类

std::atomic
中仍然没有复制构造函数。为什么此代码对 -std=c++17 有效?

当然我知道首选风格是使用

{}
,但我只是好奇为什么上面的代码从 C++17 开始编译得很好。

c++ initialization c++17 stdatomic copy-elision
1个回答
14
投票

自 C++17 起,这样的 复制省略 就得到了保证。对于

std::atomic<int> a = 0;
a
需要直接从
0
初始化。

注意:上面的规则没有指定优化:C++17 纯右值和临时变量的核心语言规范与早期 C++ 修订版的规范有根本的不同:不再有可以复制/移动的临时变量。描述 C++17 机制的另一种方式是“非物化值传递”:返回并使用纯右值,而无需物化临时值。

在 C++17 之前,即使复制/移动操作(从从

a
初始化的临时
std::atomic<int>
初始化
0
)可能会被优化(在 复制初始化中),复制/移动构造函数仍然需要可访问。

最后一步通常被优化,转换结果直接在为目标对象分配的内存中构造,但是即使不使用适当的构造函数(移动或复制)也需要可访问。 (直到 C++17)

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