2012-08-17 79 views
14

我有一个像下面这样的类。具有std :: atomic成员变量的类的复制构造函数/赋值运算符的错误

#include <atomic> 

static const long myValue = 0; 

class Sequence 
{ 

public: 

    Sequence(long initial_value = myValue) : value_(initial_value) {} 


private: 

    std::atomic<long> value_; 
}; 

int main() 
{ 
     Sequence firstSequence; 
     Sequence secondSequence = firstSequence; 
     return 0; 
} 

我越来越喜欢这个编译错误,

test.cpp:21:36: error: use of deleted function ‘Sequence::Sequence(const Sequence&)’ 
test.cpp:5:7: error: ‘Sequence::Sequence(const Sequence&)’ is implicitly deleted because the default definition would be ill-formed: 
test.cpp:5:7: error: use of deleted function ‘std::atomic<long int>::atomic(const std::atomic<long int>&)’ 

是默认的拷贝构造函数和赋值opertaor不要在这种情况下工作吗?

PS:我使用的gcc版本4.6.3

回答

14

不能使用标准拷贝构造函数复制原子,因为所有加载和存储都必须显式地进行。你必须编写你自己的Sequence的拷贝构造函数,它可以做value_(rhs.value_.load())的一些初始化(可能需要更轻松的内存排序)。

+0

你能编辑和添加一个编译代码的例子吗?我没有解决这个问题,我试过了: '序列&operator =(const序列&其他){value_ = other.value_.load();返回*这个; }' – 2017-09-28 20:50:14

+0

@VictorLamoine:不知道你做了什么,但一般的做法[作品](https://wandbox.org/permlink/ZsHPDqhrIiybq7qf)。 – 2017-09-28 21:35:18

+1

有关如何实际编写复制构造函数(使用默认的'seq_cst'来加载源代码,但是避免将原子库存储到正在构建的对象中的代价)的详细信息,请参阅[使用原子成员的类的复制构造函数](https://stackoverflow.com/questions/19961043/copy-constructor-for-classes-with-atomic-member/46045691#46045691)。确保这真的是你想要实现的;复制原子通常与共享状态的目的相反。 – 2017-10-13 01:34:14

5

因为没有std::atomic<long int>::atomic(const std::atomic<long int>&)功能,也没有办法让编译器创建的Sequence类默认的拷贝构造函数。如果你需要这个类的复制构造函数(如果你想Sequence secondSequence = firstSequence;工作,你会这样做),那么你需要编写一个。由标准所要求

此现象:

原子积分和地址类型列在下面。这些类型应具有标准布局。它们应该有一个简单的默认构造函数,constexpr显式值构造函数,删除拷贝构造函数,删除的拷贝赋值操作符以及简单的析构函数。这些类型应支持聚合初始化语法。

6

Atomic删除了copy-ctor。所以在你的课堂中复制/移动ctors被删除。

n3337 12.8/11

隐式声明的复制/移动构造函数是其类的内联公共成员。为删除的一类X A拖欠复制/移动 构造被定义(8.4.3)如果X具有:

- 类类型M(或其阵列),其不能被复制的非静态数据成员/移动,因为 重载解析(13.3),适用于M的对应的构造,导致歧义或 功能是删除或从默认的构造函数无法访问,

0

我猜想,选择删除标准中的复制构造函数有两个原因:

  • 通常需要加载/存储对。有没有什么办法可以强制这一点,当你不控制std :: atomic的调用者时呢?如果std :: atomic <>类型,你正在使用的是is_lock_free()为false(即在该实现中需要一个互斥量为整数类型)的类型?你使用什么复制语义来进行互斥锁初始化?最终隐式复制的互斥体需要重新初始化,因为它可能在锁定状态下被不幸地复制。我猜std :: mutex也有一个删除的拷贝构造函数,因此,这也将需求推入std :: atomic。

相关问题