40

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

#include <atomic>

std::atomic_int stop = 0;

int main()
{
    // Do something
}

这给了我一个编译错误:

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

知道发生了什么吗?

4

2 回答 2

48

您的代码试图std::atomic_int在 RHS 上构造一个临时对象,然后使用std::atomic_int复制构造函数(即deleted)来初始化stop,如下所示:

std::atomic_int stop = std::atomic_int(0);

那是因为copy-initialisation,正如您在此处执行的那样,并不完全等同于其他类型的初始化。

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

如果初始值设定项是(无括号的)大括号初始化列表,则对象或引用是列表初始化的(8.5.4)。

(这允许选项3,在这个答案的末尾)

[..]

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

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

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

  • 否则(即,对于剩余的复制初始化情况),可以从源类型转换到目标类型或(当使用转换函数时)到其派生类的用户定义转换序列被枚举,如 13.3 中所述。 1.4,最好的一个是通过重载决议(13.3)选择的。如果转换无法完成或不明确,则初始化格式错误。以初始化表达式作为参数调用所选函数;如果函数是构造函数,则调用初始化目标类型的 cv 非限定版本的临时版本。临时是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
于 2014-12-05T11:09:30.870 回答
-3

就我而言,我有以下错误(示例):

• 'std::literals' 尚未声明

using namespace std::literals::string_literals;

• std::random_device{} 出现“使用已删除函数”错误

std::random_device device = std::random_device{}  

检查您选择的 C++ 标准是什么。在我的调试模式下,我选择了 -std=c++17, ALL OK。但是在发布模式下,我选择了 -std:c++11,有很多错误。

更新 通过远程 Linux 编译在 Clion Windows 2018.3 上测试。

使用 -std=c++11 使用 -std=c++11

使用 -std=c++17 使用 -std=c++17

C ++ 是一个不断发展的标准:2003 年之后是 2011 年(C ++ 11),然后是 2014 年(C ++ 14),现在我们有 2017 年(C ++ 17),我们正在为 2020 年(C ++ 20)而努力) . 许多事情正在发生变化,它们已被弃用,其他功能是新的。如果你想要最新的更新,你应该使用最新的标准,如果你的软件有可能被弃用的代码,那么你必须使用创建它的标准。

于 2019-01-28T02:20:38.190 回答