C++ “使用已删除的函数”错误与 std::atomic_int
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27314485/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Use of deleted function" error with std::atomic_int
提问by Karnivaurus
I want to use an std::atomic_int
variable. In my code, I have:
我想使用一个std::atomic_int
变量。在我的代码中,我有:
#include <atomic>
std::atomic_int stop = 0;
int main()
{
// Do something
}
And this gives me a compile error:
这给了我一个编译错误:
use of deleted function 'std::__atomic_base<_IntTp>::__atomic_base(const std::__atomic_base<_IntTp>&) [with _ITp = int]'
std::atomic_int stop = 0;
^
Any idea on what's going on?
知道发生了什么吗?
回答by Lightness Races in Orbit
Your code is attempting to construct a temporary std::atomic_int
on the RHS, then use the std::atomic_int
copy constructor (which is delete
d) to initialise stop
, like so:
您的代码正在尝试std::atomic_int
在 RHS 上构造一个临时对象,然后使用std::atomic_int
复制构造函数(即delete
d)进行初始化stop
,如下所示:
std::atomic_int stop = std::atomic_int(0);
That's because copy-initialisation, as you are performing here, is not quite equivalent to other kinds of initialisation.
那是因为copy-initialisation,正如您在此处执行的那样,并不完全等同于其他类型的初始化。
[C++11: 8.5/16]:
The semantics of initializers are as follows [..]If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized(8.5.4).
[C++11: 8.5/16]:
初始值设定项的语义如下[..]如果初始值设定项是(无括号的)花括号初始化列表,则对象或引用是列表初始化的(8.5.4)。
(this allows for option 3, at the end of this answer)
(这允许选项 3,在本答案的末尾)
[..]
If the destination type is a (possibly cv-qualified) class type:
- If the initialization is direct-initialization, or if it is copy-initializationwhere the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered.The applicable constructors are enumerated (13.3.1.3), and the best one is chosen through overload resolution (13.3). The constructor so selected is called to initialize the object, with the initializer expression or expression-list as its argument(s). If no constructor applies, or the overload resolution is ambiguous, the initialization is ill-formed.
[..]
如果目标类型是(可能是 cv 限定的)类类型:
- 如果初始化是直接初始化,或者如果是复制初始化,其中源类型的 cv 非限定版本与目标类相同,或者是目标类的派生类,则考虑构造函数。枚举适用的构造函数(13.3.1.3),并通过重载决议(13.3)选择最好的构造函数。调用如此选择的构造函数来初始化对象,并将初始化表达式或表达式列表作为其参数。如果没有构造函数适用,或者重载决议不明确,则初始化格式错误。
(this almost describes your code but not quite; the key here is that, perhaps contrary to intuition, std::atomic_int
's constructors are not considered at all in your case!)
(这几乎描述了您的代码,但并不完全;这里的关键是,可能与直觉相反,std::atomic_int
在您的情况下根本不考虑 的构造函数!)
- Otherwise (i.e., for the remaining copy-initializationcases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3). If the conversion cannot be done or is ambiguous, the initialization is ill-formed.The function selected is called with the initializer expression as its argument; if the function is a constructor, the call initializes a temporary of the cv-unqualified version of the destination type. The temporary is a prvalue. The result of the call (which is the temporary for the constructor case) is then used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization.In certain cases, an implementation is permitted to eliminate the copying inherent in this direct-initializationby constructing the intermediate result directly into the object being initialized; see 12.2, 12.8.
- 否则(即,对于剩余的复制初始化情况),可以从源类型转换为目标类型或(当使用转换函数时)到其派生类的用户定义的转换序列被枚举,如 13.3 中所述。 1.4,并通过重载决议(13.3)选择最好的一个。如果转换无法完成或不明确,则初始化格式错误。选择的函数以初始化表达式作为参数被调用;如果该函数是构造函数,则调用会初始化目标类型的 cv 非限定版本的临时版本。临时是一个纯右值。调用的结果(这是构造函数情况的临时结果)然后用于直接初始化,根据上述规则,作为复制初始化目标的对象。在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除这种直接初始化中固有的复制;见 12.2、12.8。
(this is your scenario; so, although the copy can be elided, it still must be possible)
(这是你的场景;所以,虽然可以省略副本,但它仍然必须是可能的)
- [..]
- [..]
Here's the fix, anyway; use direct-initialisationor list-initialisation:
无论如何,这是解决方案;使用直接初始化或列表初始化:
std::atomic_int stop(0); // option 1
std::atomic_int stop{0}; // option 2
std::atomic_int stop = {0}; // option 3
回答by Joma
In my case I had de following errors (Examples):
就我而言,我有以下错误(示例):
? ‘std::literals' has not been declared
? 'std::literals' 尚未声明
using namespace std::literals::string_literals;
? “Use of deleted function” error with std::random_device{}
? “使用已删除的函数”错误与 std::random_device{}
std::random_device device = std::random_device{}
Check what is your selected C++ Standard. In my case on debug mode I had selected -std=c++17, ALL OK. But on Release mode I had selected -std:c++11, tons of errors.
检查您选择的 C++ 标准是什么。在我的调试模式下,我选择了 -std=c++17,一切正常。但是在发布模式下,我选择了 -std:c++11,有很多错误。
UpdateTested on Clion Windows 2018.3 with remote Linux compile.
更新在 Clion Windows 2018.3 上测试,远程 Linux 编译。
C ++ is an evolving standard: after 2003 there were 2011 (C ++ 11), then 2014 (C ++ 14) and now we have 2017 (C ++ 17) and we are working for 2020 (C ++ 20) . Many things are changing, they are deprecated, other features are new. If you want the latest update, you should use the most recent standard, if your software has code that may be deprecated then you have to use the standard with which it was created.
C ++ 是一个不断发展的标准:2003 年之后有 2011 年(C ++ 11),然后是 2014 年(C ++ 14),现在我们有 2017 年(C ++ 17),我们正在为 2020 年(C ++ 20 )。许多事情正在发生变化,它们已被弃用,其他功能是新的。如果你想要最新的更新,你应该使用最新的标准,如果你的软件有可能被弃用的代码,那么你必须使用创建它的标准。