C++ 别名规则

标签 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];
} 

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

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

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

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

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

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

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

我不是在尝试进行微优化,但我想知道目前是否最好将受限指针传递给容器,而不是引用。

编辑:澄清一些术语,正如所指出的:restrict 是 C99 关键字。在各种编译器中也有 __restrict__restrict__,但它们都做同样的事情。

最佳答案

根据strict-aliasing rule ,您不能使用指向不同类型的指针(除了 char* 和 friend )给同一内存起别名,因此情况 4 仅适用于其中一种类型是 char*.

案例 3 与案例 1 并没有什么不同,因为在我知道的所有编译器上,引用都是作为指针实现的,尽管标准不要求这样做,并且可以自由地提出其他实现。

关于C++ 别名规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6320789/

相关文章:

c++ - 尝试按值返回对象时出现无效指针错误

c++ - 如何在文件中打印位而不是字节?

c++ - 将类内部暴露给 future 谓词仿函数的良好设计机制?

c++ - 我可以使用 always emplace 代替 insert 来插入单个元素吗?

c++ - 仅在特定翻译单元中找不到头文件

c++ - 如何检查 std::array 已声明但未显式初始化

c++ - 为什么我可以在 C++ 的可变 lambda 中捕获未声明的变量

c++ - 有限状态机编译器

c++ - 将 std::list 附加到 std::list 的 vector 中

c++ - 如何启用 OpenMP w/OpenCV 应用程序?