初始化原子类成员时,它需要一个'deleted'函数,但添加它会使它不再容易复制



初始化原子类成员时,它需要一个"已删除"函数,但添加它将使其不再易于复制,这是对象/结构原子的要求。 我只是不明白如何正确执行此操作,还是这是 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的实现包含一个锁,你将如何管理原子复制它?它应该如何工作?

最新更新