这是结构黑客的C ++替代品吗?

时间:2013-11-26 10:45:39

标签: c++

以下是否有效的C ++?这是将扁平结构实现可变长度尾部的另一种方法。在C中,通常使用struct hack

struct Str
{
    Str(int c) : count(c) {}
    size_t count;
    Elem* data() { return (Elem*)(this + 1); }
};

Str* str = (Str*)new char[sizeof(Str) + sizeof(Elem) * count];
new (str) Str(count);
for (int i = 0; i < count; ++i)
    new (str->data() + i) Elem();
str->data()[0] = elem0;
str->data()[1] = elem1;
// etc...

我在回答以下related question

时问这个问题

2 个答案:

答案 0 :(得分:2)

不,它无效:

Elem可能与Str的对齐方式不同,因此(reinterpret_)将Str+1转换为Elem*可能会或可能不会为您提供有效的指针,并且访问可能会给出未定义的行为。

但毕竟为什么你想做那样的事情?

答案 1 :(得分:0)

在什么意义上有效?使用类似C的技术是C ++,只要项目要求别无选择,imho就可以了。 如果你问它是否会起作用,只要数据对齐问题不会使代码崩溃(即非x86如SPARC等)。在寻址内存时,C ++的行为与C类似。

我在gcc和VS下使用以下修改对其进行了测试,它可以工作:

struct Elem
{
Elem() : x(0), t(0) { memset(c, 0, sizeof(c));} 
Elem(int v) : x(v), t(0) { memset(c, 0, sizeof(c));} 
Elem(const Elem &e) { *this = e; }

Elem &operator=(const Elem &e)
{
    if (this != &e)
    {
         memcpy(c, e.c, sizeof(c));
         x = e.x;
         t = e.t;
    }
    return *this;
}

char c[21];
int x;
char t;
};

struct Str
{
    Str(int c) : count(c) {}
    size_t count;
    Elem* data() { return (Elem*)(this + 1); }
};

int count = 11;

Str *str = (Str*)new char[sizeof(Str) + sizeof(Elem) * count];
new (str) Str(count);
for (int i = 0; i < count; ++i)
{
    new (str->data() + i) Elem();
    str->data()[i] = Elem(i+1);
}

for (int i=0; i<str->count; i++)
    cout << "[" << i << "]: " << str->data()[i].x << endl;

另外,我向Str和Elem添加了各种不同大小的成员以强制使用不同的填充并使用对齐(VS /一些GCC:#pragma pack(...),GCC:__ attribute __((aligned(...) ))和__ attribute __(packed))。

请注意,在所有体系结构中使用对齐并不安全 - Relevant question