C ++ 17中不可复制变量的成员初始化

zingdle:

对不可复制变量(例如std::atomic<int>执行成员初始化时,需要使用direct-initialization而不是copy-initialization根据此处的答案然而,当我打开-std=c++17g++ 7.4.0,似乎后者也是行之有效的。

#include <atomic>

class A {
    std::atomic<int> a = 0;     // copy-initialization
    std::atomic<int> b{0};      // direct-initialization
};
$ g++ -c atomic.cc -std=c++11    // or c++14
atomic.cc:4:26: error: use of deleted function ‘std::atomic<int>::atomic(const std::atomic<int>&)’
     std::atomic<int> a = 0;     // copy-initialization

$ g++ -c atomic.cc -std=c++17
// no error

与编译时,它也没有g++ 6.5.0,甚至有-std=c++17这里哪一个是正确的?

songyuanyao :

自C ++ 17开始,行为发生了变化,这要求编译器省略in /的复制/移动构造std::atomic<int> a = 0;,即保证复制省略

(强调我的)

在以下情况下,即使复制/移动构造函数和析构函数具有明显的副作用,也要求编译器忽略类对象的复制和移动构造。这些对象直接构造到存储中,否则会将它们复制/移动到其中。复制/移动构造函数不需要存在或不可访问,因为语言规则可确保不会进行复制/移动操作,即使在概念上也是如此

详细地,std::atomic<int> a = 0;执行复制初始化

如果T是类类型,并且other的cv不合格版本不是T或不是从T派生的,或者T是非类类型,但是other的类型是类类型,则用户定义的转换序列可以将其他类型转换为T(如果T是类类型并且可以使用转换函数,则可以转换为从T派生的类型),然后通过重载分辨率选择最佳的。转换结果(prvalue temporary (until C++17) prvalue expression (since C++17)如果使用了转换构造函数,则为a)然后用于直接初始化对象。

(强调我的)

如果T是类类型,并且初始化程序是prvalue表达式,其cv不合格类型与T是同一类,则初始化程序表达式本身(而不是从其实例化的)用于初始化目标对象

这意味着a可以0直接初始化,没有临时构造,再也没有临时要复制/移动。

在C ++ 17之前,概念上std::atomic<int> a = 0;需要std::atomic从中构造一个临时文件0,然后将该临时文件用于copy-construct a

在C ++ 17之前甚至允许复制省略,它被认为是一种优化:

(强调我的)

这是一种优化:即使发生并且move (since C++11)未调用copy / 构造函数,它也必须存在并且可以访问(好像根本没有优化发生),否则程序格式错误

这就是为什么gcc在c ++ 17之前的模式下触发的诊断的原因std::atomic<int> a = 0;

(强调我的)

注意:上面的规则未指定优化:prvalues和temporaries的C ++ 17核心语言规范与早期C ++修订版的根本不同:不再需要从中复制/移动的临时属性描述C ++ 17机制的另一种方法是“未实现的值传递”:prvalue的返回和使用无需实现一个临时值

顺便说一句:我认为g++ 6.5.0with中有一个错误-std=c++17并且已在更高版本中修复。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章