请考虑以下代码:
Class* p = nullptr; //global var
此代码由线程1执行:
p = new Class;
此代码在线程2上执行:
if (p != nullptr) ...; // does the standard gurantee that the pointer will be assigned only after object is constructed ?
我的问题是,当p
被分配为指向已分配的内存时,标准是否会强制执行?
例1:
p
被指定为指向新分配的内存Class
调用c`tor并将分配的内存传递给它示例2:
Class
调用c`tor并将分配的内存传递给它p
被指定为指向新分配的内存答案 0 :(得分:6)
根据标准,如果两个线程中的这些操作未同步,则行为未定义。
C ++ 11草案N3337,
[intro.multithread] / 4:
两个表达式评估冲突如果其中一个修改了内存位置(1.7)而另一个修改了内存位置 访问或修改相同的内存位置。
[intro.multithread] / 21:
如果程序的执行包含数据竞争,如果它在不同的线程中包含两个冲突的动作, 其中至少有一个不是原子的,也不会发生在另一个之前。任何此类数据竞赛都会产生 未定义的行为。
C ++ 14的相应引用基本相同。
至于p = new Class;
的执行顺序,与示例2中的执行顺序类似,因为首先评估new Class
,然后进行赋值(提供Class
的构造函数或operator new
没有抛出异常。)
[expr.ass] / 1:
在所有情况下,分配都在值之后排序 计算右和左操作数,并在赋值表达式的值计算之前。
答案 1 :(得分:0)
不,该标准不保证这样的事情。
要修复它,你需要在构造对象和指定指针之间有一个内存屏障,以便它们之间存在线程之间发生的关系:
Class* tmp = new Class();
// you need a memory barrier here
p = tmp;
在c ++ 11中,您使用std::atomic
来引入内存障碍:
std::atomic<Class*> p;
在这种情况下,最好使用store()
而不是分配:
p.store(tmp, std::memory_order_release);