以下是否有效的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
时问这个问题答案 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