【问题标题】:initializing a class or struct with an atomic array用原子数组初始化一个类或结构
【发布时间】:2014-02-04 05:22:52
【问题描述】:

如何使用原子变量数组编写用户定义的类/结构的复制构造函数?例如下面的代码无法编译

struct foo
{    
     std::array<std::atomic_int,3> a;
     foo() = default;
     foo(const int& i, const int& j, const int& k):a{{i,j,k}}{}
}

因为“错误:在此处声明 __atomic_base(const __atomic_base&) = delete;”即这在原子类型的定义中被删除。如果它是非原子的,它就会完成。

有没有办法做到这一点?

我已经在C++ - How to initialise an array of atomics? 进行了讨论。

【问题讨论】:

  • 注意:foo(const int&amp; i, const int&amp; j, const int&amp; k) 不是复制构造函数。如果您想编写该构造​​函数,则需要更多的大括号(这通常会有所帮助;)foo(const int&amp; i, const int&amp; j, const int&amp; k):a{{{i},{j},{k}}} {} 这与聚合初始化有关,它调用聚合成员的复制初始化。跨度>
  • 嗨@dyp,感谢您指出这一点。问题现在解决为 foo(const int& i, const int& j, const int & k){a[0].store(int(i)); a[1].store(int(j)); a[2].store(int(k));}。谢谢!

标签: arrays c++11 atomic copy-constructor initializer-list


【解决方案1】:

std::atomic 复制构造函数被删除,因为没有办法将值从一个对象原子地复制到另一个对象:

std::atomic<int> a, b;
a = b; //  use of deleted function 'std::atomic<int>& std::atomic<int>::operator=(const std::atomic<int>&)'

但是,您可以从一个原子读取值,然后将读取的内容存储到另一个原子中,您只需要一些不舒服的语法来明确表明您不需要原子副本:

std::atomic<int> a, b;
a = b.load();

您可以使用 for 循环以这种方式复制原子数组:

std::array<std::atomic<int>, 3> a, b;
for (const auto& i : b) {
  a = i.load();
}

或 - 为了避免显式循环 - 转换:

std::array<std::atomic<int>, 3> a, b;
std::transform(begin(b), end(b), begin(a),
               [](int i){return i;});

所以我会将你的复制构造函数实现为:

foo(const foo& other) {
    std::transform(begin(other.a), end(other.a), begin(a),
                   [](int i){return i;});
}

【讨论】:

  • @dyp 对于一般情况来说是个好主意,但它会使 transforms 的 lambda 有点奇怪。我不会写 std::transform(begin(b), end(b), begin(a), [](decltype(*b.cbegin()) i){return i.load();}) 除非通用性是绝对关键的,尽管我可能会在复制构造函数中使用 [](decltype(other.a[0]) i){return i.load();} 来编写我编写的代码,而不是 SO 答案。 [](const auto&amp; foo){return foo.load()} 当然会很好 - 我假设 OP 没有 C++14 编译器;)
  • @dyp tsk,tsk - 复制!抱歉,我的编辑踩到了你。
  • :D ok... 一时糊涂
  • 大家好,Casey 和@dyp,非常感谢您的精彩回答和知情讨论。我的目的是将用户定义的复制构造函数编写为 foo(const int& i, const int& j, const int & k) 并且确实从你的讨论中得到线索我现在将它作为 foo(const int& i, const int& j, const int & k){a[0].store(int(i)); a[1].store(int(j)); a[2].store(int(k));} 它工作得很好。我不能赞成你的答案,因为我没有那么多的名声,但是,我确实想这样做。 dyp 请为这个讨论点赞。
【解决方案2】:

只需手动定义复制构造函数,并在构造函数的主体中逐个元素复制数组元素(如果应该复制的话)。请注意,这不是原子的。

【讨论】:

  • 嗨@SebastianRedl,我试过了,但由于您已经提到的谨慎原因,它不能正常工作。我的目的是为这个类编写一个构造函数,但是即使 a 不是数组,它也不起作用。
猜你喜欢
  • 2014-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多