#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 的了解是它应该与完整的对象类型一起使用。 [表达式.new]
在 [class.dtor] §12.4 (14) 中有一个带有放置选项的新表达式示例。但是,该示例可能会起作用,因为其中的类是标准布局。
最佳答案
Where is the guarantee that the layout created by new fits into a buffer of size sizeof(B) and with offset zero
来自 new
中命名的类型因为它的论点是B
. B
正在制作,而不是 D
.类型B
“对D
一无所知” . D
的声明对B
没有影响; B
声明可以放入翻译单元中D
没有出现,但在程序中的任何地方都会对 B
的大小达成一致。并且是布局,不管是否D
在那些地方也有名有无。
T
类型的 C++ 对象大小为 sizeof T
.这意味着它适合 sizeof T
字节;不可能是(sizeof T) + k
它的表示需要字节,其中 k > 0
.
关于c++ - placement new 如何知道要创建哪个布局?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39946780/