指针容器的指针别名

时间:2015-05-17 16:05:24

标签: c++ pointers stl containers alias

我了解到指针别名可能会影响性能,并且__restrict__属性(在GCC中,或其他实现中的等效属性)可能有助于跟踪哪些指针应该或不应该别名。同时,我还了解到GCC的valarray实现存储了一个__restrict__'ed指针({3}}中的第517行),我认为暗示了编译器(和负责用户)的私有指针可以假设valarray方法中的任何地方都没有别名。

但是如果我们为指向valarray对象的别名添加别名,例如:

#include <valarray>

int main() {
    std::valarray<double> *a = new std::valarray<double>(10);
    std::valarray<double> *b = a;
    return 0;
}

是否可以说a的成员指针也有别名?并且b的存在是否会损害valarray方法可能带来的任何优化? (指向优化的指针容器是不好的做法吗?)

2 个答案:

答案 0 :(得分:1)

让我们首先了解如何别名会损害优化。

考虑这段代码,

void
process_data(float *in, float *out, float gain, int nsamps)
{
    int i;
    for (i = 0; i < nsamps; i++) {
        out[i] = in[i] * gain;
    }
}
  

在C或C ++中,参数inout指向内存中的重叠区域是合法的....当编译器优化函数时,通常不知道是否inout是别名。因此,必须假设通过out的任何商店都会影响in指向的内存,严重限制了它重新排序或并行化代码的能力(对于一些简单的情况,编译器可以分析整个程序)确定两个指针不能是别名。但一般来说,编译器不可能确定两个指针是否是别名,所以为了安全起见,它必须假定它们是。)


来到你的代码,

#include <valarray>

int main() {
    std::valarray<double> *a = new std::valarray<double>(10);
    std::valarray<double> *b = a;
    return 0;
}

由于ab是别名。 valarray使用的底层存储结构也会有别名(我认为它使用了一个数组。对此不太确定)。因此,以类似于上面所示的方式使用ab的代码的任何部分都不会受益于编译器优化,例如并行化和重新排序。请注意,b的存在不会影响优化,但会如何使用它。

现金: 引用的部分和代码来自here。这也可以作为有关该主题的更多信息的良好来源。

答案 1 :(得分:0)

  

是否可以说a的成员指针也是别名?

是。例如,a->[0]b->[0]引用相同的对象。那个别名。


  

b的存在是否会损害valarray方法可能带来的任何优化?

没有

您尚未在示例代码中使用b完成任何操作。假设您的函数比以相同构造开头的示例代码大得多。如果该函数的前几行使用a但从不b,则通常没有问题,其余行使用b但从不使用a。通常。 (然而,优化编译器会重新排列代码行。)

另一方面,如果您将ab混合使用,则不会对优化造成影响。你正在做更糟糕的事情:你正在调用未定义的行为。 &#34;不要这样做&#34;是未定义行为问题的最佳解决方案。

<强>附录

C restrict和gcc __restrict__关键字不是对编译器或标准库的开发人员的约束。这些关键字是编译器/库的承诺,限制数据不会与其他数据重叠。编译器/库没有检查程序员是否违反了这个承诺。如果此承诺启用某些可能因重叠数据而无效的优化,则编译器/库可以自由应用这些优化。

这意味着restrict(或__restrict__)是对您的限制,而不是编译器。即使没有b指针,您也可以违反这些限制。例如,考虑

*a = a->[std::slice(a.size()-1,a.size(),-1)];

这是未定义的行为。