新的表达式求值顺序(指针赋值)
new expression evaluation order (pointer assignment)
考虑以下代码:
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:
- new表达式调用运算符new
p
被指派指向新分配的存储器- 调用
Class
的c`tor并将分配的内存传递给它
示例2:
- new表达式调用运算符new
- 调用
Class
的c`tor并将分配的内存传递给它 p
被指派指向新分配的存储器
根据标准,如果两个线程中的这些操作不同步,则行为是未定义的。
C++11草案N3337,
[介绍.多线程]/4:
两个表达式求值冲突如果其中一个修改内存位置(1.7)而另一个修改访问或修改相同的存储器位置。
[介绍.多线程]/21:
程序的执行包含数据竞赛,如果它在不同线程中包含两个冲突的操作,其中至少有一个不是原子的,也没有发生在另一个之前。任何此类数据竞赛都会导致未定义的行为。
C++14中相应的引用基本上是相同的。
至于p = new Class;
的执行顺序,就像您的示例2中一样,因为首先计算new Class
,然后进行赋值(前提是Class
或operator new
的构造函数没有抛出异常)。
[expr.ass]/1:
在所有情况下,赋值都在值之后排序右操作数和左操作数的计算以及在赋值表达式的值计算之前。
不,标准不能保证这样的东西。
为了解决这个问题,你需要在对象的构造和指针的分配之间设置一个内存屏障,这样在它们之间的关系之前就会发生线程间的事情:
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);
相关文章:
- 错误:在为指针赋值时,void值没有被忽略
- 关于 c++ 函数中指针赋值的简单问题
- 链表指针赋值为什么我们不能直接将尾巴分配给 temp 而不是尾巴>尾巴下一个
- 为什么通过指针赋值常量没有效果?
- 复制构造函数中的指针赋值
- C++ 指针赋值运算符重载(不仅是对象赋值,还有指针赋值)
- 从字符串数组打印其中一个字符串时出现空指针赋值错误
- 为字符串指针赋值
- 动态指针赋值c++
- std::wstring指针赋值C++
- C++匿名结构指针赋值
- 为指针赋值而不赋值
- 此指针赋值应生成段错误
- 指向指针赋值的指针
- 哪个指针赋值更好(C++)
- <T>unique_ptr.get() 方法在使用原始指针赋值时调用析构函数?
- 为用soap_alloc创建的std::string指针赋值
- 为什么函数头的更改会导致指针赋值不起作用
- 64位c++指针赋值
- 在函数中将指针赋值到不同的地址