【发布时间】:2012-10-14 23:42:27
【问题描述】:
我发现自己最近越来越多地使用 C++11,在过去我会使用迭代器的地方,我现在尽可能使用 range-based for loops:
std::vector<int> coll(10);
std::generate(coll.begin(), coll.end(), []() { return rand(); } );
C++03:
for (std::vector<int>::const_iterator it = coll.begin(); it != coll.end(); ++it) {
foo_func(*it);
}
C++11:
for (auto e : coll) { foo_func(e); }
但是如果集合元素类型是模板参数呢? foo_func() 可能会被重载以通过 const 引用传递复杂(= 复制昂贵)类型,并通过值传递简单类型:
foo_func(const BigType& e) { ... };
foo_func(int e) { ... };
我在使用上面的 C++03 风格的代码时没有考虑这么多。我会以同样的方式进行迭代,因为取消引用 const_iterator 会产生一个 const 引用,所以一切都很好。但是使用 C++11 基于范围的 for 循环,我需要使用 const 引用循环变量来获得相同的行为:
for (const auto& e : coll) { foo_func(e); }
突然间我不确定了,如果auto 是一个简单类型(例如实现引用的幕后指针),这是否不会引入不必要的汇编指令。
但是编译一个示例应用程序证实了简单类型没有开销,而且这似乎是在模板中使用基于范围的 for 循环的通用方式。如果不是这样,boost::call_traits::param_type 将是正确的选择。
问题:标准中是否有任何保证?
(我意识到这个问题实际上与基于范围的 for 循环无关。使用 const_iterators 时也存在。)
【问题讨论】: