默认初始化标准::原子<;T*>;vs无锁堆栈 在威廉姆斯的C++并发操作第二中。第213页有一个无锁栈的实现(如下所示)。它泄漏节点,因此是不完整的,但这与我的问题无关。我的问题是他没有显式初始化std::atomic head指针,然后在pop()函数中取消引用它——这不是未定义的行为吗
据 默认初始化的默认初始化标准::原子<;T*>;vs无锁堆栈 在威廉姆斯的C++并发操作第二中。第213页有一个无锁栈的实现(如下所示)。它泄漏节点,因此是不完整的,但这与我的问题无关。我的问题是他没有显式初始化std::atomic head指针,然后在pop()函数中取消引用它——这不是未定义的行为吗,c++,C++,据 默认初始化的std::atomic不包含T对象,其唯一有效用途是通过std::atomic_init 所有指针类型的部分专门化std::atomic。这些专门化具有标准布局、普通默认构造函数和普通析构函数 我想我看不到什么,因为(甚至更不完整) 在上实现无锁堆栈也不重要 初始化原子头指针。有人能给我解释一下为什么这个用法是合法的吗 这是Wiliams的密码 template<typename T> class lock_free_stack { private: str
std::atomic
不包含T对象,其唯一有效用途是通过std::atomic_init
所有指针类型的部分专门化std::atomic
。这些专门化具有标准布局、普通默认构造函数和普通析构函数
我想我看不到什么,因为(甚至更不完整)
在上实现无锁堆栈也不重要
初始化原子头指针。有人能给我解释一下为什么这个用法是合法的吗
这是Wiliams的密码
template<typename T>
class lock_free_stack
{
private:
struct node
{
std::shared_ptr<T> data;
node* next;
node(T const& data_):
data(std::make_shared<T>(data_))
{}
};
std::atomic<node*> head; // <-- Default constructor
public:
void push(T const& data)
{
node* const new_node=new node(data);
new_node->next=head.load();
while(!head.compare_exchange_weak(new_node->next,new_node));
}
std::shared_ptr<T> pop()
{
node* old_head=head.load();
while(old_head &&
!head.compare_exchange_weak(old_head,
old_head->next));// uninitialized ptr?
return old_head ? old_head->data : std::shared_ptr<T>();
}
};
模板
类锁\u自由\u堆栈
{
私人:
结构节点
{
std::共享的ptr数据;
节点*下一步;
节点(T常数和数据):
数据(标准::使共享(数据))
{}
};
std::atomic head;//next=head.load();
而(!head.compare_exchange_弱(新建节点->下一步,新建节点));
}
std::共享的\u ptr pop()
{
节点*old_head=head.load();
当(老)头&&
!头。比较你的交换弱(老头,
旧头->下一步);//未初始化的ptr?
返回旧头?旧头->数据:std::shared_ptr();
}
};
只有在读取时未初始化的变量,才能读取未初始化的变量。如果在读取之前先用一个值初始化它,就可以了。@Nicolas如果我没弄错的话,这两个函数都读取(并实际使用)存储在默认初始化头指针中的值。更糟糕的是,pop()取消了对这个指针的引用。另外,无锁栈的构造函数在哪里?@nicolabolas似乎只有合成的默认构造函数。据我所知,威廉姆斯说——除了泄漏节点之外——这应该是一个完整的实现。换句话说——这正是我的问题,我们是否必须在堆栈的构造函数中将head初始化为nullptr。