解决c ++严格别名规则

时间:2013-03-22 00:17:35

标签: c++ strict-aliasing

我想在容器中存储有限数量的项目。我不想使用数组,因为我想避免不必要的对象构造函数调用。我不想使用std::vector因为隐式malloc调用(我希望最小化对堆的访问以实现最大缓存一致性)。

所以我开始定义我自己的自定义容器,如下所示:

template<typename T, size_t capacity> class my_array {
  private:
   char buffer[sizeof(T)*capacity];
   ...
  public:
   T& operator[](size_t i) { return *(T*)&buffer[i*sizeof(A)]; }
   ...
};

但是当我尝试实际使用此容器时,我收到有关违反严格别名规则的编译器警告。我已经阅读了严格别名,我理解为什么编译器优化会导致上述代码中断。

我该如何解决这个问题?

奇怪的是,我的编译器没有抱怨我的自定义object_pool类,除其他外,我用于我的关联STL数据结构的自定义分配器。该类看起来与上面的类似(使用char[]并执行类似的演员)。我无法弄清楚两者之间的区别是什么。

4 个答案:

答案 0 :(得分:1)

使用std::array 。 。 。 。 。 。 。 。 。 。 。 。 。 !

答案 1 :(得分:1)

如果您不打算使用std:array,那么

char buffer[sizeof(T)*capacity];

应该是

T buffer[capacity]

这就是模板首先支持typename的原因。

答案 2 :(得分:1)

如果您不想按std::aligned_storage的要求初始化对象,请使用std::array。您可能会遇到对齐问题,因为您的结构可能会被分配到奇数地址。

使用char数组进行别名以将其用作存储应该没问题,我不确定您的编译器是关于什么的。这真的是一个最小的测试用例吗?

答案 3 :(得分:0)

通过精确地比较我在原帖中提到的object_pool课程,我找到了一个神秘的解决方案。

我替换了

T& operator[](size_t i) { return *(T*)&buffer[i*sizeof(A)]; }

T* operator[](size_t i) {
  if (...) {
    return (T*)&buffer[i*sizeof(A)];
  }
  return NULL;
}

其中...是我知道将始终评估为true的任何谓词,但编译器不够聪明,将始终评估为true

如果有人能够在这里准确地解释编译器的内容,我会很好奇。我正在使用gcc 4.4.3。