【发布时间】:2010-12-18 18:47:28
【问题描述】:
当 C++ 函数接受 std::vector 参数时,通常的模式是通过 const 引用传递它,例如:
int sum2(const std::vector<int> &v)
{
int s = 0;
for(size_t i = 0; i < v.size(); i++) s += fn(v[i]);
return s;
}
我相信这段代码在访问向量元素时会导致双重取消引用,因为 CPU 应该首先取消引用 v 以读取指向第一个元素的指针,而需要再次取消引用该指针才能读取第一个元素。我希望在堆栈上传递向量对象的浅表副本会更有效。这种浅拷贝会封装一个指向第一个元素的指针和大小,该指针引用的内存区域与原始向量相同。
int sum2(vector_ref<int> v)
{
int s = 0;
for(size_t i = 0; i < v.size(); i++) s += fn(v[i]);
return s;
}
类似的性能,但通过传递随机访问迭代器对可以实现的便利性要小得多。 我的问题是:这个想法有什么缺陷?我希望聪明人应该有充分的理由接受支付向量引用的性能成本,或者处理迭代器的不便。 p>
编辑:根据下面的评论,如果我只是将建议的 vector_ref 类重命名为 slice 或 range,请考虑这种情况。目的是使用语法更自然的随机访问迭代器对。
【问题讨论】:
-
你真的对比过两种情况下生成的机器码吗?还是测量性能?
-
你有没有检查过它在组装时确实如此?我也不认为迭代器对的约定来自性能考虑,它是设计决策(实际上,boost 更倾向于迭代器范围对象的更方便的概念,即使我还没有研究它们是如何工作的)。
-
我认为您的 cmets 实际上没有任何意义。引用是对象的别名。因此,访问对对象的引用并不像访问原始对象那样昂贵。这种略带煽动性的谩骂是你的猜测,如果你做了两分钟的尽职调查,你就不需要这篇文章了。
-
@Martin:引用是一个带有语法糖的指针。说真的。
-
引用是不能重新定位的指针(指向不同的对象)。由于此属性,编译器可能能够更有效地优化使用引用而不是指针的代码。但是引用确实与对象本身有很大的不同。