为什么对象的初始化调用复制构造函数? [英] Why does the initialisation of an object invoke the copy constructor?

查看:111
本文介绍了为什么对象的初始化调用复制构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下最小工作示例:

Consider the following minimal working example:

#include <atomic>

int main() {
  ::std::atomic<bool> a = false;
}

原子的复制ctor和复制分配均被明确删除.但是,这应调用 ctor并采取精确的布尔值.

Copy ctor and copy assignment of atomic are both explicitly deleted. However, this should invoke the ctor taking exactly a bool.

g ++和clang ++都抱怨这行试图调用 atomic 的副本ctor:

Both g++ and clang++ complain that this line is attempting to invoke the copy ctor of atomic:

$ g++ -std=c++1z a.cpp 
a.cpp: In function ‘int main()’:
a.cpp:4:27: error: use of deleted function ‘std::atomic<bool>::atomic(const std::atomic<bool>&)’
   ::std::atomic<bool> a = false;
                           ^~~~~
$ clang++ -std=c++1z a.cpp 
a.cpp:4:23: error: copying variable of type '::std::atomic<bool>' invokes deleted constructor
  ::std::atomic<bool> a = false;
                      ^   ~~~~~

为什么他们要复制 atomic ?

推荐答案

它尝试调用副本构造函数,因为其move构造函数已被隐式删除.

It tries to invoke the copy constructor because its move constructor has been implicitly deleted.

假设我们有一个X类.

struct X
{
    X(const X&) = delete; // user-declared

    X(int)
    {
    }
};

现在,如果你要写

X x = 4;

它将与

X x = X(4); // copy/move into x, see 15.6.1

,你会得到的编译错误,因为您显式删除了复制构造函数,因此没有隐式声明任何move构造函数.

and you would get a compilation error because you explicitly deleted the copy constructor and therefore no move constructor is being implicitly declared.

15.8.1复制/移动构造函数

[...]

如果类X的定义未明确声明移动构造函数,则仅当且仅当非显式类的隐式声明为默认值

If the definition of a class X does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if

  • X没有用户声明的副本构造函数,
  • X没有用户声明的副本分配运算符,
  • X没有用户声明的移动分配运算符,并且
  • X没有用户声明的析构函数.

[注意:当未隐式声明move构造函数或明确提供的表达式,否则将调用move构造函数可以代替调用副本构造函数.— 尾注]

[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. — end note ]

在C ++ 17中,这种情况随着引入保证的复制省略.
这导致该行等于

In C++17 this changes with the introduction of guaranteed copy elision.
This results in the line being equal to

X x(4);

不依赖于复制或移动构造函数,而是调用 X(int).

which does not rely on either copy or move constructor and instead calls X(int).

X std::atomic 也将其副本构造函数明确删除这就是为什么如果不使用C ++ 17支持进行编译,则代码将无法编译的原因.

Like X, std::atomic also has its copy constructor explicitly deleted which is why your code fails to compile if not compiled with C++17 support.

这篇关于为什么对象的初始化调用复制构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆