c++ - 如何在编译时计算 C++11 中的结构填充?

标签 c++ c++11 sizeof

问题

我有一个 std::vector 的大量 Foo 的

struct Foo
{
  int   m_i;
  char  m_c;
  char  m_padding[3];   // want to replace this
};

我可以一次以二进制形式快速写入这 block 连续的 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;
};

最佳答案

嗯,我可以看到两种方式:

  1. 使用类的 union 和与类一样大的 char 数组
  2. 使用模板化类和元编程找出所有填充

不用说前者似乎更容易,所以现在开始:

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

关于c++ - 如何在编译时计算 C++11 中的结构填充?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21969456/

相关文章:

C++ 在配置之间切换的最佳方式

c++ - 如何播种随机数生成器?

c - 在 C 语言中,sizeof 是以八位字节还是字符来衡量其结果?

c# - 使用 c++ 中的 "long"进行互操作 c#

c++函数在之后立即调用析构函数

c++ - 从最小堆 C++ 创建霍夫曼代码树

c++ - 如何将 DeviceIOControl 移植到 ioctl?

c++ - 返回没有复制构造函数的引用

c++ - 如何从 OpenSSL 中获取随机盐作为 std::string

c - 为什么 sizeof 运算符对某些表达式的工作方式不同?