我发现自己最近越来越多地使用 C++11,过去我会使用迭代器,现在我尽可能使用基于范围的 for 循环:
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 时也存在。)