在C ++中使用placement new执行的操作的完整列表是什么?

时间:2009-06-23 09:32:17

标签: c++ constructor new-operator

this question中,当编译器不支持 new 并且放置 new 时,会创建工厂方法。显然,如果以某种方式复制放置 new 所做的所有必要步骤,可以使用malloc()制作一些合适的解决方案。

展示位置做什么 - 我会尝试列出并希望不要错过任何内容 - 除了以下内容?

  • 递归调用所有基类的构造函数
  • 为所有成员变量调用构造函数和初始值设定项(如果有)
  • 相应地设置vtable指针。

还有其他什么行动?

3 个答案:

答案 0 :(得分:6)

放置new执行常规new所做的一切,除了分配内存。

我认为你基本上已经把所发生的事情钉在了一些细微的说明上:

  • 显然,类本身的构造函数也被调用
  • vtable指针初始化为构造函数调用的一部分,而不是单独的。这意味着部分构造的对象(想想构造函数中抛出的异常)将其vtable设置为构造进行到的点。

构造/初始化的顺序如下:

  1. 声明顺序中的虚拟基类
  2. 声明顺序中的非虚拟基类
  3. 声明顺序中的班级成员
  4. 类构造函数本身

答案 1 :(得分:4)

相应地设置vtable指针

这部分几乎完全是实现定义的。您的编译器可能不使用vtables。可能有多个vtable指针,或者指向不是vtable的东西的一个或多个指针。多重继承总是很有趣,虚拟基类也是如此。不保证此元数据可以使用memcpy复制到另一个对象,因此指针不必是绝对的。那里可能存在相对于对象指针本身的偏移。

IIRC通常发生的是调用基类构造函数,然后将vtable指针设置为基类,然后调用第一个派生类构造函数等。这是为了满足规范中的要求在构造函数中调用虚函数时会发生什么。据我记忆,标准中没有“行动清单”,只是定义了初始化顺序。

因此无法概括实现的功能,特别是因为您所拥有的不是C ++标准的实现。如果它通过省略“新”来削减角落,可能有充分的理由,因为它认为你不应该在目标平台上使用它,那么谁知道它忽略的语言的其他规则。如果可以使用malloc和一些指针推动来模拟“new”,那么为什么编译器不仅仅实现新的呢?我认为您需要提出用您的特定编译器和平台标记的问题,以便编译器上的任何专家都能做出响应。

答案 2 :(得分:0)

@laalto回答一般都是正确的。但是,有一个例外证明了这一规则。

  

vtable指针初始化为构造函数调用的一部分,而不是单独的。

Microsoft C ++编译器知道所谓的本地vftables,即vftables是DLL的本地,并且将为每个导入的类克隆。这是因为编译器想要提供一个修改后的析构函数,它包装了原始的析构函数(s.a. here)。

每当构造导入类的对象时,编译器都会在构造函数调用后生成用本地指针覆盖原始vftable指针的代码。此代码也会出现在新的来电中。

除了上面的帖子中提到的那些之外,还存在另一种解决方法。此解决方法不会强制您更改原始头文件。请看这里:https://godbolt.org/g/YQsffY