考虑以下C 11代码:
#include <type_traits>
struct bar
{
virtual void do_bar() const {}
};
struct foo
{
std::aligned_storage<sizeof(bar),alignof(bar)>::type m_storage;
};
由于虚函数 do_bar()
, bar
不是标准布局 . 但是, foo
是标准布局,因为 std::aligned_storage
提供的类型是POD类型, foo
满足标准布局类型的所有其他要求 .
当我使用带有 new
的 m_storage
存储来构建 bar
的实例时会发生什么?例如 . ,
foo f;
::new(static_cast<void *>(&f.m_storage)) bar();
这合法吗?我可以用它来欺骗我对标准布局类型的限制吗?
3 回答
这是你的代码:
这可以 .
struct foo
是标准布局类型,并且在给定实例foo myFoo
的情况下,您可以将bar
类型的对象构造为myFoo.m_storage
.但是,这对编译器的POV来说完全没有意义,为什么还要烦恼呢?正如@dyp在评论中明智地说的那样,“你为什么要让foo成为标准布局?”
你手动了一些关于工会的事情 . 嗯,那没关系 . 你可以这样写:
但是,同样明显的是,你不能指望 this 工作:
换句话说,你可以自由地欺骗编译器(通过type-punning和reinterpret_cast),但这并不能使你的谎言成真 . ;)
另见:XY problem.
在OSX的XCode C 11编译器选项中尝试过,似乎对我有用 . 当然,你可能想做“:: new(static_cast(&f.m_storage))bar();”在foo的构造函数中,在foo的析构函数中调用它的析构函数 .
使用对齐的数量时
1)建议使用 declspec(align(16)) or __attribute ((aligned(16)))为类或结构指定对齐方式 . 我在使用VS2010进行优化时遇到了一些错误,当时我没有这样做 .
2)我通常避免重载新的并使用您建议的放置操作符,例如
3)一个好的经验法则是在结构或类的开头放置对齐的数量 . 这样编译器就不会在成员之间进行零填充,并对此发出警告 .