#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
,而不是D
。 B
类型对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/