是否有任何一般偏好或规则可以解释何时应使用容器特定版本的begin和end而不是自由函数std::begin
和std::end
?
据我了解,如果函数是一个模板,其中容器类型是模板参数,则应使用std::begin
和std::end
,即:
template<class T> void do_stuff( const T& t )
{
std::for_each( std::begin(t), std::end(t), /* some stuff */ );
}
在其他方案中,例如已知容器类型的标准/成员函数?使用std::begin(cont)
和std::end(cont)
或者容器的成员函数cont.begin()
和cont.end()
是首选是否仍然是更好的做法?
我是否认为通过cont.end()
调用std::end(cont)
对性能没有任何好处?
答案 0 :(得分:72)
免费功能版本比容器的成员功能更通用。我可能会在通用代码中使用它,其中容器的类型之前是未知的(并且可能是数组)。在其余的代码中(即当容器被修复并且已知时),由于惯性,我可能会使用c.begin()
。我希望有关C ++的新教科书可以推荐免费的功能版本(因为它永远不会更糟,有时候会更好),但这必须赶上常用的用法。
答案 1 :(得分:31)
如果你看一下std::begin
的定义:
template< class C >
auto begin( C& c ) -> decltype(c.begin());
你知道它所做的只是参考begin()
。我想一个不错的编译器会使差异为零,所以我猜它归结为偏好。就个人而言,我只使用cont.begin()
和cont.end()
,以便我不必向任何人解释:)
正如Mooing Duck指出的那样,std::begin
也适用于数组:
template< class T, size_t N >
T* begin( T (&array)[N] );
......所以有需要考虑的问题。如果你不使用数组,我会接受我的建议。但是,如果您不确定传递的内容是STL容器还是<T>
数组,那么std::begin()
就可以了。
答案 2 :(得分:10)
除非某些优化被关闭以进行调试,否则使用cont.begin()
(或获取指向第一个元素的指针,或其他任何东西)将没有性能优势,除非有人提供了一个非常奇怪的实现!几乎所有的实现(当然还有STL的实现)都是晶圆级的,并且在编译器的口中融化。
正面在上面的“或者其他”中:相同的代码适用于不同的集合类型,无论是来自STL,还是数组,还是第三方的一些奇怪的集合,如果他们认为提供了开始的专业化为了它。即使你从未使用过它,begin()
也是众所周知的,应该有熟悉的好处。