为什么Visual C++ 2015允许std::atomic赋值?

8
几天前我写了以下内容:
struct A {
    std::atomic_bool b = false;
};

使用Visual Studio 2015 Update 3及其VC++2015编译器编译时,没有出现任何问题。
现在我用Ubuntu上的GCC (5.4.0)重新编译同样的东西,却遇到了错误:

use of deleted function 'std::atomic::atomic(const std::atomic&)

我在ideone上也遇到了同样的错误,设置为C++14(不确定使用哪个编译器版本)。

当然,将代码更改如下可以解决gcc的问题:
struct A {
    std::atomic_bool b { false };
};

我的问题是:
1. 在这里,VC++和GCC谁是正确的(C++11兼容)?看起来VC++调用了bool的构造函数,而GCC则调用了复制构造函数(已删除)。
2. 为了在类声明中默认值初始化原子变量,统一初始化(如上所示)是正确/首选的方式吗?还是应该使用ATOMIC_VAR_INIT宏(呃!)?

struct A {
    std::atomic_bool b = ATOMIC_VAR_INIT(false);
};

1
请参见https://dev59.com/2mEi5IYBdhLWcg3wDoaV。至于问题#2,请不要使用“ATOMIC_VAR_INIT”,这主要是为了C11兼容性。 - interjay
1个回答

2

VC在这里是错的。在C++17之前,代码X x = y的语义意思是调用X tmp(y)然后调用X(tmp) - 也就是说,语义上有一个复制构造函数的调用。

虽然我知道的所有编译器都会消除中间调用(标准允许这样做),但程序仍然不合法。看起来VC没有正确执行语义。

在C++17中,这个调用的语义将会改变,并且只需要一个初始化构造函数的调用,因此代码将变得合法。


我想知道VC++2015是否已经实现了C++17草案中的某些内容。 - roalz
@roalz 在C++11程序中仍然是错误的。 - Surt
1
@Surt 当然,据我所知,VC++2015更新3应该默认具有/std:c++14开关(就像我的情况一样):https://blogs.msdn.microsoft.com/vcblog/2016/06/07/standards-version-switches-in-the-compiler/。因此,这绝对是一个VC++兼容性问题。 - roalz
Visual Studio团队采取了同时实现C++14和C++17的方法,因此在一些C++14的部分之前已经实现了C++17的一些特性。看起来这是他们已经实现了C++17的其中一个领域。 - Sjoerd
@Sjoerd 但是这会与默认的 /std:c++14 编译器开关不一致。我的意思是,如果我指定编译器使用 c++14,则从 c++17 中包含部分内容是错误的。而且,由于在 C++14 中我的情况是不合规的,我希望 VC++ 像以 c++14 模式运行的 GCC 一样给出错误。 - roalz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接