C++别名规则

Dar*_*rda 21 c++

只是想知道是否有人会为我确认一些别名规则.

我知道别名(即加载存储问题)可能导致以下类型的代码不是最理想的,因为我们不能假设x, y, z不重叠:

// case 1:
void plus(size_t n, double *x, double *y, double *z)
{
    for (size_t i = 0; i != n; ++i)
        z[i] = x[i] + y[i];
} 
Run Code Online (Sandbox Code Playgroud)

我知道有一个C关键字__restrict提示编译器它不应该考虑重叠的情况,因此可能生成更好的代码:

// case 2:
void plus(size_t n, double *__restrict x, double *__restrict y, double *__restrict z)
{ // as above... }
Run Code Online (Sandbox Code Playgroud)

但是,别名如何使用C++样式代码,我们将处理通过引用传递的容器对象,而不是上面带有原始指针的C类示例?

例如,我假设如果我们执行以下操作会出现别名问题:

// case 3:
void plus(std::vector<double> &x, std::vector<double> &y, std::vector<double> &z)
{ // similar to above... }
Run Code Online (Sandbox Code Playgroud)

并且转移到一个不那么简单的例子,如果容器中的底层数据类型不同,它会有什么不同吗?在实现级别,大多数容器使用指针动态管理存储,因此我不清楚编译器如何确保以下不是别名:

// case 4:
void foo(std::vector<mytype1> &x, std::vector<mytype2> &y)
{ // interwoven operations on x, y... }
Run Code Online (Sandbox Code Playgroud)

我不是想进行微优化,但我想知道目前是否更好地将限制指针传递给容器,而不是引用.

编辑:要清除一些术语,如指出:restrict是C99关键字.还有__restrict,并__restrict__在不同的编译器,但他们都做同样的事情.

Xeo*_*Xeo 8

根据严格别名规则,不允许使用指向不同类型(除了char*和朋友)的指针对同一内存进行别名,因此情况4只能在其中一种类型为a时应用char*.

案例3虽然与案例1没有什么不同,因为引用被实现为我所知道的所有编译器上的指针,尽管标准并没有要求它,并且实现可以自由地提出其他内容.


Luc*_*ton 5

它根本不是针对 C++ 的。考虑这个 C99 位:

struct vector {
    double* data;
    size_t n;
};

void
plus(struct vector* restrict x, struct vector* restrict y, struct vector* restrict z)
{
    // same deal as ever
}
Run Code Online (Sandbox Code Playgroud)

在这里,restrict购买我们很少:x->datay->data并且z->datadouble*和允许别名。这与情况 1 完全一样,即使使用了限制。

如果restrict在 C++ 中有一个关键字(或者在使用扩展时),最好的办法可能是plus(vecA.size(), &vecA[0], &vecB[0], &vecB[0])使用与plus情况 2相同的方法。 事实上,现在可以这样做,使用 C89 风格的接口,而没有restrict但是在封面下使用关键字。