何时使用std :: begin和std :: end而不是容器特定版本

时间:2011-12-09 21:49:41

标签: c++ c++11

是否有任何一般偏好或规则可以解释何时应使用容器特定版本的begin和end而不是自由函数std::beginstd::end

据我了解,如果函数是一个模板,其中容器类型是模板参数,则应使用std::beginstd::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)对性能没有任何好处?

3 个答案:

答案 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()也是众所周知的,应该有熟悉的好处。