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

是否有任何一般的首选项或规则来解释什么时候应该使用容器特定版本的 start 和 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)对性能没有任何好处,这种假设是正确的吗?

28946 次浏览

If you look at, say, the definition of std::begin:

template< class C >
auto begin( C& c ) -> decltype(c.begin());

You see that all it does is reference the begin() anyway. I suppose a decent compiler will make the difference nil, so I guess it comes down to preference. Personally, I'd use cont.begin() and cont.end() just so that I wouldn't have to explain it to anybody :)

As Mooing Duck points out, however, std::begin also works on arrays:

template< class T, size_t N >
T* begin( T (&array)[N] );

... so there is that to consider. If you are not using arrays, I'd go with my suggestion. However if you are unsure if what is passed is going to be an STL container, or an array of <T>, then std::begin() is the way to go.

Barring some optimisations being turned off to debug, there won't be a performance benefit to using cont.begin() (or getting a pointer to the first element, or whatever) unless someone's provided a really weird implementation! Pretty much all implementations (and certainly those with STL) are wafer-thin and melt in the compiler's mouth.

The plus-side is in the "or whatever" above: The same code works across different collection types whether another from the STL, or arrays, or some bizarre collection by a third party if they thought to supply a specialisation of begin for it. Even if you never use that, begin() is well-known enough that there should be a familiarity benefit.

The free function version is more generic than the member function of the container. I would use it probably in generic code where the type of the container is not known before hand (and might be an array). In the rest of the code (i.e. when the container is fixed and known) I would probably use c.begin() due to inertia. I would expect new text books on C++ to recommend the free function version (as it is never worse and sometimes better), but that has to catch up with common usage.