1

在堆上构造对象是 C++ 语言中看似简单的任务。当代码

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

被调用,我的理解是内存必须先分配,然后初始化,最后调用类的构造函数。此外,对象的虚拟表在构建完成之前不一定可用。

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

提前致谢。

4

4 回答 4

6

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

于 2013-06-26T13:41:41.587 回答
1

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

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

于 2013-06-26T13:41:42.870 回答
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未完全构造的值。

于 2013-06-26T13:44:06.840 回答
0

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

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

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

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

我的问题是:operator new 能否在对象完成构造之前返回指向已分配/初始化内存的指针?

operator new 总是在 ctor 启动之前运行并完成。

但是您可能是指new operator问题中的 as 。只有当一切都完成时才会返回,ctor 完成了它的工作。

于 2013-06-26T13:42:59.013 回答