在施工完成之前,操作员可以获得新的返

时间:2013-06-26 13:35:03

标签: c++ multithreading new-operator

在堆上构造对象在C ++语言中看起来很简单。当代码

T* object = new T();
func(object);
调用

,我的理解是必须首先分配内存,然后初始化,最后调用类的构造函数。此外,在构造完成后

之前,对象的虚拟表不一定可用。

我的问题是:operator new可以在对象构建完成之前返回指向已分配/初始化内存的指针,以便func(...)对未完全构造的对象进行操作吗?这个问题的答案对我正在开发的多线程库有影响。

提前致谢。

4 个答案:

答案 0 :(得分:6)

operator new分配内存。 new关键字(在示例代码中使用)使用operator new来分配内存,然后构造该内存中的对象。并且,是的,在没有正确同步的多线程应用程序中,指针值可以在构造函数的副作用发生之前在其他线程中可见。这是因为每个处理器都可以有一个单独的缓存,并且在构造函数的副作用被读入缓存之前,指针值可能会被读入缓存。阅读“双重检查锁定”了解更多详情。

答案 1 :(得分:1)

object在构造之前不会指向对象。 new T()在完成之前不会返回。

我猜Pete Becker的缓存问题是正确的......

答案 2 :(得分:1)

我认为产生operator new()值的T* object = new T();object之间存在混淆。

如果我们非常简单地看一下(这仅仅是为了说明目的,并不意味着C ++编译器实际上如何做事的精确定义),我们可以将T* object = new T();分解为几个部分:

 void *temp = ::operator new(sizeof(T));  // Now we have SPACE for a T object. 
 (T*)temp->T();       // Construct the contents of T. 
 object = (T *)temp;    // assign `object`. 

(对于学生的注意事项:上面的代码并不是有效的C ++,也不是“如何使用一个C ++语句并将其变为三个” - 它用于描述表单中一行中发生的事情有合理但没有C ++专业知识的人可以理解。

它按此顺序发生,除非你的构造函数启动一个执行“完成构造”工作的线程,否则你不能在object中创建一个未完全构造的值。

答案 3 :(得分:0)

  

必须首先分配内存,然后初始化,最后调用类的构造函数。

我不知道中间步骤。对于您的表单,operator new被调用,然后是前者返回的内存上的构造函数。

  

此外,在构建完成之前,对象的虚拟表不一定可用。

它是可用的 - 在某种意义上(标准根本不要求VMT,只是行为),简单来说,在构造过程中,类的行为就好像它是活动ctor的“最多派生”。可以发出虚拟调用但它们从Base :: Base()调用Base :: foo,如果从init列表调用,则必须注意某些部分尚未构建。

  

我的问题是:运算符new可以在对象构造完成之前返回指向已分配/初始化内存的指针吗?

operator new 始终在ctor启动之前运行并完成。

但你的意思可能是new operator。只有当一切都完成后,ctor才能完成它的工作。