考虑这个问题:我有一个用户类型的atomic_ref
。我想同时访问它的成员函数。参见以下代码:
struct A{
int counter=0;
int add(){
++counter;
return counter;
};
};
int main() {
A a;
std::atomic_ref<A> ra{a};
std::vector<std::thread> v;
for(int i=0;i<1000;++i){
v.emplace_back([&ra]{ra.load().add();});
};
for(auto & t: v){t.join();};
std::cout<<a.counter<<std::endl;
};
最终输出是0
,因为load()
返回一个副本。有没有其他方法可以通过atomic_ref
得出正确的结果?
我还想问,如果我们有一个atomic_ref<T*>
,我们可以使用load()
来访问成员函数,例如ra.load()->add()
吗。它安全吗?代码将变成这样:
struct A{
int counter=0;
int add(){
++counter;
return counter;
};
};
int main() {
A* a=new A;
std::atomic_ref<A*> ra{a};
std::vector<std::thread> v;
for(int i=0;i<1000;++i){
v.emplace_back([&ra]{ra.load()->add();}); //Accessing member functions.
};
for(auto & t: v){t.join();};
std::cout<<a->counter<<std::endl;
};
在我的测试中,它确实是1000
,这是正确的。
原子不是魔法。它们只影响引用本身的加载和访问,而不影响通过引用访问的任何内容。