Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对齐的存储和标准布局_C++_C++11 - Fatal编程技术网

C++ 对齐的存储和标准布局

C++ 对齐的存储和标准布局,c++,c++11,C++,C++11,考虑以下C++11代码: #include <type_traits> struct bar { virtual void do_bar() const {} }; struct foo { std::aligned_storage<sizeof(bar),alignof(bar)>::type m_storage; }; 这合法吗?我可以用它来绕过标准布局类型的限制吗?在OSX的XCode C++11编译器选项中尝试过,似乎对我很有效。当然,您可能

考虑以下C++11代码:

#include <type_traits>

struct bar
{
    virtual void do_bar() const {}
};

struct foo
{
    std::aligned_storage<sizeof(bar),alignof(bar)>::type m_storage;
};

这合法吗?我可以用它来绕过标准布局类型的限制吗?

在OSX的XCode C++11编译器选项中尝试过,似乎对我很有效。当然,您可能希望在foo的构造函数中执行“::new(static_cast(&f.m_storage))bar()”,并在foo的析构函数中调用其析构函数

使用对齐数量时

1) 建议使用declspec(align(16))或uu属性(aligned(16))为类或结构指定对齐方式。我在使用VS2010启用优化时遇到了一些错误,当时我没有这样做

2) 我通常避免重载new,并像你建议的那样使用placement操作符,例如

#include <new> // Remember this otherwise the placement operator is not defined
SomeClass* c = (SomeClass*) _mm_malloc(sizeof(SomeClass),16);
new c SomeClass(); // This is perfectly legal
// Some work
_mm_free(c);
#include//记住这一点,否则不会定义placement运算符
SomeClass*c=(SomeClass*)mm\u malloc(sizeof(SomeClass),16);
新的c SomeClass();//这是完全合法的
//一些工作
_无毫米(c);

3) 一个好的经验法则是在结构或类的开头放置对齐的数量。这样,编译器就不会在成员之间进行零填充并发出警告。

这是您的代码:

struct bar {
    virtual void do_bar() const {}
};

struct foo {
    std::aligned_storage<sizeof(bar), alignof(bar)>::type m_storage;
};
但是,同样明显的是,您不能期望这一点起作用:

struct car {
    int initialsequence;
};
struct bar {
    int initialsequence;
    virtual void do_bar() const {}
};
struct foo {
    std::aligned_storage<sizeof(bar), alignof(bar)>::type m_storage;
    bar& asBar() { return *reinterpret_cast<bar*>(&m_storage); }
};

union JustSilly {
    foo f;
    car c;
} js;
assert(&js.c.initialsequence ==         // Fails, because no matter how many
       &js.f.asBar().initialsequence);  // casts you add, bar still has a vptr!
struct-car{
int初始序列;
};
结构条{
int初始序列;
虚拟void do_bar()常量{}
};
结构foo{
标准::对齐的存储::类型m存储;
bar&asBar(){return*reinterpret_cast(&m_storage);}
};
工会真傻{
福福;
c车;
}js;
assert(&js.c.initialsequence==//失败,因为无论有多少个
&js.f.asBar().initialsequence);//如果您添加了强制转换,bar仍然有一个vptr!
换句话说,你可以自由地对编译器撒谎(通过类型双关和重新解释),但这并不能让你的谎言成真


另请参见:

“我可以用它来绕过标准布局类型的限制吗?”您指的是什么?例如,为什么希望/需要
foo
成为标准布局?@DyP:例如,参见9.2.1中关于共享公共初始序列的标准布局类的联合的特殊规则。例如:
structfoo2{aligned_storage::type m_storage;int i;};联盟u{foo2 m0;foo m1;}对没有非标准布局类型的非静态数据成员的标准布局类型的限制似乎与占用存储[intro.object]/5的连续性有关,这在这里是不相关的(
m_存储
确实占用了连续存储,因为它本身就是标准布局).据我所知,这会导致foo成为一种标准布局类型,具有实现定义的大小和对齐方式。它也不允许标准布局,比如进入酒吧。简言之,它应该适合一些,但不是所有的使用标准布局。。。可能吧。如果你的设计没有搞砸,那么你几乎很少需要新的布局(在一些低级库中:容器、反射/序列化等等),即使在这些情况下,也不会有对齐阻碍你。在我看来,不要把时间浪费在思考如何编写不应该编写的代码上…:-)
union DoesntWork {
    bar b;    // compiler error in C++11 due to non-standard-layout type
    int i;
};

union DoesWork {
    foo f;    // works fine in C++11, of course
    int i;
};
struct car {
    int initialsequence;
};
struct bar {
    int initialsequence;
    virtual void do_bar() const {}
};
struct foo {
    std::aligned_storage<sizeof(bar), alignof(bar)>::type m_storage;
    bar& asBar() { return *reinterpret_cast<bar*>(&m_storage); }
};

union JustSilly {
    foo f;
    car c;
} js;
assert(&js.c.initialsequence ==         // Fails, because no matter how many
       &js.f.asBar().initialsequence);  // casts you add, bar still has a vptr!