初始化原子类成员时,它需要一个"已删除"函数,但添加它将使其不再易于复制,这是对象/结构原子的要求。 我只是不明白如何正确执行此操作,还是这是 c++ 标准中的问题?
举个例子:
#include <atomic>
#include <cstdint>
template<typename T>
struct A
{
T * data;
std::atomic<uintptr_t> next;
};
template<typename T>
class B
{
std::atomic<A<T>> myA;
public:
B ( A<T> & a ) noexcept
{
myA.store(a, std::memory_order_relaxed );
}
};
int main ()
{
A<int> a;
B<int> b(a);
return 0;
}
尝试用 g++ 编译它会得到error: use of deleted function 'A<int>::A(const A<int>&)' myA.store(a, std::memory_order_relaxed);
. 我对此错误的理解是atomic::store方法正在我的struct A
中查找该构造函数,但没有找到它。
现在,当我添加该构造函数时,会发生什么情况:
#include <atomic>
#include <cstdint>
template<typename T>
struct A
{
T * data;
std::atomic<uintptr_t> next;
A(const A<T>& obj) { }
A( ) { }
};
template<typename T>
class B
{
std::atomic<A<T>> myA;
public:
B ( A<T> & a ) noexcept
{
myA.store(a, std::memory_order_relaxed );
}
};
int main ()
{
A<int> a;
B<int> b(a);
return 0;
}
我不再收到上述编译器错误,而是来自原子类要求的新错误required from 'class B<int>' .... error: static assertion failed: std::atomic requires a trivially copyable type ...
换句话说,通过添加使用的定义的构造函数,我使我的struct A
成为一个无法在class B
中初始化的不可复制的对象。 但是,如果没有用户定义的构造函数,我就无法在myA.store(a, std::memory_order_relaxed)
中使用store
方法。
这似乎是std::atomic
类设计中的一个缺陷。 现在也许我只是做错了什么,因为我没有很多使用 C++11 及更高版本的经验(我是老派)。 自 11 年以来,发生了很多变化,要求似乎要严格得多。 我希望有人能告诉我如何实现我想要实现的目标。
我也无法std::atomic<A<T>> myA;
更改为std::atomic<A<T>> * myA;
(更改为指针)或std::atomic<A<T>*> myA;
. 我意识到这将编译,但它会破坏我正在尝试构建的类的基本设计。
这里的问题在于std::atomic
需要一个简单可复制的类型。这是因为平凡可复制的类型是C++中唯一确定的类型,可以通过直接复制其内存内容(例如通过std::memcpy
)直接复制。此外,非以前平凡可复制的类型对于原始副本可能是安全的,但不能对此做出假设。
这对std::atomic
确实很重要,因为临时值的复制是通过std::memcpy
进行的,例如,请参阅Clang的一些实现细节。
现在同时std::atomic
不是可复制的,这是出于合理的原因,例如检查这个答案,所以它隐含地不是可复制的(也不是任何包含它们的类型)。
如果荒谬的是,你允许一个std::atomic
包含另一个std::atomic
,并且std::atomic
的实现包含一个锁,你将如何管理原子复制它?它应该如何工作?