C++ 如何在c++;11在编译时?
问题 我有一个无数个Foo的std::向量C++ 如何在c++;11在编译时?,c++,c++11,sizeof,C++,C++11,Sizeof,问题 我有一个无数个Foo的std::向量 struct Foo { int m_i; char m_c; char m_padding[3]; // want to replace this }; 我可以一次快速地以二进制形式编写这段连续的Foo 我的问题是,如果我不显式地输入m_填充,计算它,然后自己清除它,valgrind会抱怨未初始化的写入 问题 是否可以在C++11中编写一个模板类,在编译时为我计算填充 如果是这样,我可以将其添加到我所有的Foo的末尾,并自动
struct Foo
{
int m_i;
char m_c;
char m_padding[3]; // want to replace this
};
我可以一次快速地以二进制形式编写这段连续的Foo
我的问题是,如果我不显式地输入m_填充,计算它,然后自己清除它,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;
};
模板
结构BZero
{
BZero(){std::memset(this,0,sizeof(T));}
};
结构Foo:public BZero
{
国际货币基金组织;
charm_c;
};
我不确定自己是否理解得很好,那么这个呢:
struct FooBase {
int i;
char c;
};
template<typename T, size_t total>
struct padded : public T {
char pad[total-sizeof(T)];
};
typedef padded<FooBase, 8> Foo;
structfoobase{
int i;
字符c;
};
模板
填充结构:公共T{
炭垫[总尺寸(T)];
};
typedef加垫Foo;
我可以看到两种方法:
联合体和与类一样大的字符数组
template <typename T>
class ZeroedClass {
public:
template <typename... Args>
ZeroedClass(Args&&... args) {
new (&_.t) T(std::forward<Args>(args)...);
}
// Need other special members as well
~ZeroedClass() { _.t.~T(); }
// Accessors
T& access() { return _.t; }
T const& get() const { return _.t; }
private:
union U {
U() { memset(this, 0, sizeof(T)); }
char buffer[sizeof(T)];
T t;
} _;
}; // class ZeroedClass
模板
类零类{
公众:
模板
ZeroedClass(Args&&…Args){
新的(&u.t)t(标准:正向(args)…);
}
//还需要其他特别成员吗
~ZeroedClass(){{uu.t.~t();}
//访问者
T&access(){return}.T;}
T const&get()const{return}
私人:
联合大学{
U(){memset(this,0,sizeof(T));}
字符缓冲区[sizeof(T)];
T;
} _;
}; // 类零类
在填充其他字段之前,您可以使用memset
清除整个结构。一般来说,您的结构可能在成员之间也有填充,valgrind会(或至少应该)同样抱怨这一点,并且在末尾添加填充成员并不能解决这个问题。@hvd我喜欢您的建议-我可以创建一个类模板,该模板在该构造函数中作为参数Foo和memset。这样,Foo仍然可以以正常方式初始化。我会尝试一下,如果效果好,我会更新OP。注意:如果您从基类派生,则允许编译器将派生类成员隐藏在基类填充中。@MatthieuM。出于好奇:您知道有任何编译器实际执行此优化吗?@pmrstruct S1{int a;char b;~S1(){};结构S2:S1{char c;};int main(){return sizeof(S2)-sizeof(S1);}
在我的系统(32位模式和64位模式下的x64 Linux)上返回0。但是由于我不知道的原因,如果析构函数被移除,它不会发生在我的系统上。