#include <iostream>
#include <typeinfo>
struct A { int a; };
struct B : virtual A { int b; };
struct C : virtual A  { int c; };
struct D : B,C { int d; };
int main()
{
  D complete;
  B contiguous;
  B & separate = complete;
  B * p[2] = {&separate, &contiguous};
  // two possible layouts for B:
  std::cout<< (int)((char*)(void*) &p[0]->a -(char*)(void*)&p[0]->b)<<" "<< sizeof(*p[0])<< "\n";
  std::cout<< (int)((char*)(void*) &p[1]->a -(char*)(void*)&p[1]->b)<<" "<< sizeof(*p[1])<< "\n";

  alignas(B) char buff[sizeof(B)];
  void * storage = static_cast<void*>(buff);
  // new expression skips allocation function:
  auto pointer= new (storage) B;        // Which layout to create?
  std::cout << typeid(pointer).name()<<"\n";
  pointer->~B();    // Destructor knows layout through typed pointer.
}
// sample output (Debian 8, amd64):
// 24 16
// 4 16
// P1B

C++ 14标准中是否有一节要求"new"创建特定的布局?有没有保证
新创建的布局适合大小为sizeof(B)且偏移量为零的缓冲区吗?

编辑:您能否使用grep友好的术语或提供引用?我在问题中添加了对标准的引用。

考虑以上示例输出:数字24告诉您什么?缓冲区的大小是多少?

标准中可能有这样一种说法,即派生程度最高的对象始终是对象表示形式的直接且连续的副本,
但我还没找到

我们对new的了解是,它将与完整的对象类型一起使用。 [expr.new]

[class.dtor]§12.4(14)中有一个带放置选项的new表达式示例。但是,该示例可能仅因为其中的类是标准布局而起作用。

最佳答案



从类型中以new命名的类型作为其参数为B。正在生成B,而不是DB类型对D“一无所知”。 D的声明对B没有影响;可以将B声明放入不出现D的翻译单元中,但是程序中的每个地方都会对B的大小和布局达成一致,无论是否在这些地方也知道D

类型为T的C++对象的大小为sizeof T。这意味着它适合sizeof T字节;不能以(sizeof T) + k字节来表示,k > 0

关于c++ - 新的展示位置如何知道要创建哪个布局?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39946780/

10-09 13:31