在此Stack Overflow answer 证明了C ++中的别名会降低代码的速度。 C ++中的别名不仅适用于指针,也适用于引用,更常见的是these types specified by the standard。特别是,有
聚合或联合类型,其成员中包含上述类型之一(包括递归地,子聚合或包含联合的成员)
所以根据我的理解,如果我有如下代码,
class A{
public:
int val;
};
void foo(vector<A> & array, int & size, A & a0) {
for(int i=0;i<size;++i) {
array[i].val = 2*a0.val;
}
}
a0
可能会为array
中的某个元素添加别名,也可能是别名size
,因为上述引用,所以a0
和{{1必须为每次迭代加载,导致性能下降。
size
无济于事,因为它不会避免标准规定的别名。按值传递const &
?但这会复制我不喜欢的a0
,因为在实践中,类a0
可能非常复杂,复制是一个非常昂贵的选择。答案 0 :(得分:7)
{+ 3}}似乎涵盖了避免C ++中的别名性能问题,而Evolution Working Group issue 72: N4150 Alias-Set Attributes: Toward restrict-like aliasing semantics for C++, N3988 Towards restrict-like aliasing semantics for C++ N3635 Towards restrict-like semantics for C++ 是该提案的最新版本。 EWG问题尚未解决,但显然已准备好进行审核。
该提案提出C类限制限定符,这些限定符目前由许多编译器在C ++中由扩展支持但具有模糊区域,该提案还说明了其他内容:
毫无疑问,限制限定符有益于编译器 在许多方面进行优化,特别是允许改进的代码运动和 消除负荷和商店。自推出C99以来 限制,它在许多编译器中作为C ++扩展提供。 但是这个特性在C ++中很脆弱,没有明确的C ++语法规则 和语义。现在随着C ++ 11的引入,仿函数正在出现 用lambdas替换,用户已经开始询问如何使用restrict 在lambdas面前。鉴于现有的编译器支持,我们 之前需要提供具有明确定义的C ++语义的解决方案 使用一些常见的C99限制子集变得广泛使用 与C ++ 11结构组合。
该提案还指出:
没有标准化和改进现有的C99 在C ++中限制设施,用户通常必须跳过相当多的环节来实现其效果 通过临时代码重写代码,或者分解和内联函数体来模拟其效果。
所以看起来目前还没有好的解决方案,虽然目前的编译器有扩展,提供C限制像语义,但有很多灰色区域 3。 C ++和C 中的限制问题涵盖了一些用于避免别名的方法,但它们都有缺陷。
该提案提到了N4150,其中提到了与这些技术相关的一些技术和缺陷。例如:
克服别名的最简单方法是复制 潜在的别名参数。
void rf2(type& output, const type& input) { type temp = input; output += ra1(temp); output += ra2(temp); }
这种技术比简单技术更复杂,效率更低 按值传递参数。虽然这种技术在使用时很有用 处理遗留接口时,它不应该是主要技术。
此技术适用于您的情况。
注意有趣的别名和C99限制限定符N3538。
答案 1 :(得分:1)
如果目的是在执行foo期间你不期望size
或a0.val
发生变化,那么你可以通过将这些变为本地值来明确表达:
void foo(vector<A> & array, int size, const A & a0) {
auto new_val = 2*a0.val;
for(int i=0;i<size;++i) {
array[i].val = new_val;
}
}
现在很明显,您打算将所有元素设置为相同的值。读者和编译器都很清楚。