"使用已删除的函数"错误与std :: atomic_int

Kar*_*rus 24 c++ c++11 stdatomic

我想使用std::atomic_int变量.在我的代码中,我有:

#include <atomic>

std::atomic_int stop = 0;

int main()
{
    // Do something
}
Run Code Online (Sandbox Code Playgroud)

这给了我一个编译错误:

use of deleted function 'std::__atomic_base<_IntTp>::__atomic_base(const std::__atomic_base<_IntTp>&) [with _ITp = int]'
 std::atomic_int stop = 0;
                        ^
Run Code Online (Sandbox Code Playgroud)

对于发生了什么有什么想法?

Lig*_*ica 30

您的代码正在尝试std::atomic_int在RHS上构造临时代码,然后使用std::atomic_int复制构造函数(即deleted)进行初始化stop,如下所示:

std::atomic_int stop = std::atomic_int(0);
Run Code Online (Sandbox Code Playgroud)

这是因为你在这里执行的复制初始化并不完全等同于其他类型的初始化.

[C++11: 8.5/16]:初始化器的语义如下[..]

如果初始化程序是(非括号的)braced-init-list,则对象或引用是列表初始化的(8.5.4).

(这允许选项3,在这个答案的最后)

[..]

如果目标类型是(可能是cv限定的)类类型:

  • 如果初始化是直接初始化,或者它是复制初始化,其中源类型的cv-nonqualified版本与目标类相同的类或派生类,则考虑构造函数.列举了适用的构造函数(13.3.1.3),并通过重载解析(13.3)选择最佳构造函数.调用所选的构造函数来初始化对象,初始化表达式或表达式列表作为其参数.如果没有构造函数适用,或者重载决策是不明确的,则初始化是错误的.

(这几乎描述了你的代码,但并不完全;这里的关键是,也许与直觉相反,std::atomic_int在你的情况下根本不考虑构造函数!)

  • 否则(即,对于剩余的复制初始化情况),可以如13.3中所述枚举可以从源类型转换为目的地类型或(当使用转换函数时)到其派生类的用户定义的转换序列. 1.4,通过重载决策(13.3)选择最好的一个.如果转换不能完成或不明确,则初始化是错误的.选择的函数以初始化表达式作为参数调用; 如果函数是构造函数,则调用初始化目标类型的cv-nonqualified版本的临时函数.临时是一个prvalue.然后,根据上面的规则,调用的结果(对于构造函数的情况是临时的)用于直接初始化作为复制初始化目标的对象.在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除此直接初始化中固有的复制; 见12.2,12.8.

(这是你的场景;所以,尽管副本可以省略,但仍然必须可行)

  • [..]

无论如何,这是修复; 使用直接初始化列表初始化:

std::atomic_int stop(0);     // option 1
std::atomic_int stop{0};     // option 2
std::atomic_int stop = {0};  // option 3
Run Code Online (Sandbox Code Playgroud)

  • 选项3:`std :: atomic_int stop = {0};`.这是复制初始化,但是使用braced-init-list的复制初始化执行复制列表初始化,这不涉及临时(在这种情况下). (3认同)
  • 啊,是的,我找到了措辞.来袭待命! (2认同)