【问题标题】:Getting around c++ strict-aliasing rules绕过 C++ 严格别名规则
【发布时间】:2013-03-11 17:33:23
【问题描述】:

我想在一个容器中存储有限数量的项目。我不想使用数组,因为我想避免不必要的对象构造函数调用。我不想使用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[] 并执行类似的转换)。我不知道这两者有什么区别。

【问题讨论】:

  • 你不能用std::array吗?或者std::tr1::arrayboost::array 你们中没有C++11 支持?
  • 我没有 c++11 支持。即使我这样做了……我的另一个要求是,出于性能原因,我不想立即实际调用 T 的构造函数。我应该提到这个要求,我会编辑我的帖子。

标签: c++ strict-aliasing


【解决方案1】:

通过与我在原始帖子中提到的 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。

【讨论】:

    【解决方案2】:

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

    char 数组混叠以将其用作存储应该没问题,我不确定您的编译器在做什么。这真的是一个最小的测试用例吗?

    【讨论】:

    • re “使用 char 数组进行别名以将其用作存储应该没问题”。对于纯粹的形式,这里的 char 数组不需要为 T 适当对齐。它不是动态分配的数组。在实践中,如果 OP 具​​有虚函数或其他东西,则数组不需要位于结构的开头,因此即使结构适当对齐,数组也不需要。
    • 如果添加my_array&lt;int,4&gt; 的实例化,然后使用[] 运算符,那么是的,它是一个最小的测试用例。我也很困惑,因为我认为char 有一个例外。
    • 很遗憾,没有c++11支持,所以不能使用std::aligned_storage。
    【解决方案3】:

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

    char buffer[sizeof(T)*capacity];
    

    应该是

    T buffer[capacity]
    

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

    【讨论】:

    • 有没有办法在不调用T的构造函数的情况下做到这一点?
    • 没有。这让事情变得更加困难。
    【解决方案4】:

    使用std::array . . . . . . . . . . . . . !

    【讨论】:

      猜你喜欢
      • 2015-05-31
      • 1970-01-01
      • 2015-10-15
      • 2017-02-25
      • 2011-02-15
      • 2019-01-29
      • 2018-10-27
      • 2018-12-14
      • 1970-01-01
      相关资源
      最近更新 更多