首页 文章

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

提问于
浏览
83

这个问题在这里已有答案:

是否有任何一般首选项或规则可以解释何时应使用容器特定版本的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 回答

  • 72

    如果你看一下 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() 是可行的方法 .

  • 9

    自由函数版本比容器的成员函数更通用 . 我可能会在通用代码中使用它,其中容器的类型之前是未知的(并且可能是数组) . 在其余的代码中(即当容器被修复并且已知时),由于惯性,我可能会使用 c.begin() . 我希望C上的新教科书可以推荐免费的功能版本(因为它永远不会更糟,有时甚至更好),但这必须赶上常见用法 .

  • 30

    除非某些优化被关闭以进行调试,否则使用 cont.begin() (或获取指向第一个元素的指针,或其他任何东西)将没有性能优势,除非有人说出来 .

    加号在上面的"or whatever"中:相同的代码适用于不同的集合类型,无论是来自STL,还是数组,还是第三方的一些奇怪的集合,如果他们想为它提供begin的特化 . 即使你从不使用它, begin() 也是众所周知的,应该有熟悉的好处 .

相关问题