【发布时间】:2014-02-23 14:24:02
【问题描述】:
问题
我有一个巨大的 Foo 的 std::vector
struct Foo
{
int m_i;
char m_c;
char m_padding[3]; // want to replace this
};
我可以一次将这块连续的 Foo 快速写入二进制形式。
我的问题是,如果我不明确输入那个 m_padding、计算它并自己清除它,valgrind 会抱怨未初始化的写入。
问题
是否可以在 C++11 中编写一个模板类来在编译期间为我计算填充?
如果是这样,我可以将它添加到我所有 Foo 的末尾并自动初始化/清除它们,而不会受到 valgrind 的投诉。
我可以通过计算 sizeof( padding ) = sizeof( Foo ) - sum( sizeof(parts )) 手动完成,但最好为这个计算创建某种类,因为所有信息都可以在编译时获得-时间。
为简单起见,假设 Foo 具有微不足道的布局(type_traits 是一个重要但切题的问题)。另外,请忽略订购问题/跨平台问题。
可能的方法
这并没有直接回答我原来的问题,但 hvd 的建议暗示了一种更简单的方法,似乎适用于我尝试过的一些简单测试用例:
template<typename T>
struct BZero
{
BZero() { std::memset( this, 0, sizeof( T )); }
};
struct Foo : public BZero<Foo>
{
int m_i;
char m_c;
};
【问题讨论】:
-
您可以在填写其他字段之前使用
memset清除整个结构。一般来说,你的结构可能在成员之间也有填充,valgrind 会(或至少应该)同样抱怨,并且在最后添加一个填充成员不会解决这个问题。 -
@hvd 我喜欢你的建议——我可以创建一个类模板,在该构造函数中将 Foo 和 memset 作为参数。这样,Foo 仍然可以以正常方式初始化。如果一切正常,我会尝试一下并更新 OP。谢谢。
-
注意:如果您从基类派生,编译器可以将派生类成员隐藏在基类填充中。
-
@MatthieuM。出于好奇:您知道实际执行此优化的任何编译器吗?
-
@pmr
struct S1 { int a; char b; ~S1() {} }; struct S2 : S1 { char c; }; int main() { return sizeof(S2) - sizeof(S1); }在我的系统上返回 0(x64 Linux,在 32 位模式和 64 位模式下)。但是由于我不知道的原因,如果删除了析构函数,它就不会在我的系统上发生。