每个标准容器具有begin和end方法,返回的迭代器是容器.然而,C++ 11显然已经引入自由函数调用std::begin和std::end该调用begin和end成员函数.所以,而不是写作
auto i = v.begin();
auto e = v.end();
Run Code Online (Sandbox Code Playgroud)
你会写的
using std::begin;
using std::end;
auto i = begin(v);
auto e = end(v);
Run Code Online (Sandbox Code Playgroud)
在他的演讲中,编写现代C++,Herb Sutter说当你想要容器的开始或结束迭代器时,你应该总是使用自由函数.但是,他没有详细说明你想要的原因.查看代码,它可以为您节省一个字符.因此,就标准容器而言,自由函数似乎完全没用.Herb Sutter表示非标准容器有好处,但他再次没有详细说明.
因此,问题是除了调用相应的成员函数版本之外,自由函数版本究竟做了什么,std::begin并且std::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 */ );
}
Run Code Online (Sandbox Code Playgroud)
在其他场景中,例如已知容器类型的标准/成员函数呢?它仍然是更好的做法是使用std::begin(cont)和std::end(cont)或应容器的成员函数cont.begin()和cont.end()首选?
我在假设有通过调用在性能上没有任何好处纠正cont.end()过std::end(cont)?
当创建一个按照通常规则播放的自定义容器类(即使用STL算法,使用性能良好的通用代码等)时,在C++ 03中实现迭代器支持和成员开始/结束函数就足够了.
C++ 11引入了两个新概念 - 基于范围的for循环和std :: begin/end.基于范围的for循环理解成员开始/结束函数,因此任何C++ 03容器都支持基于范围的开箱即用.对于算法,推荐的方法(根据Herb Sutter的'Writing modern C++ code')是使用std :: begin而不是member function.
但是,此时我不得不问 - 是否建议调用完全限定的begin()函数(即std :: begin(c))或依赖ADL并调用begin(c)?
在这种特殊情况下,ADL似乎毫无用处 - 因为如果可能的话,std :: begin(c)委托给c.begin(),通常的ADL好处似乎不适用.如果每个人都开始依赖ADL,那么所有自定义容器都必须在其必需的命名空间中实现额外的begin()/ end()自由函数.但是,有几个消息来源似乎暗示对开始/结束的不合格调用是推荐的方式(即https://svn.boost.org/trac/boost/ticket/6357).
那么C++ 11的方式是什么?容器库作者是否应该为其类编写额外的开始/结束函数,以便在没有使用namespace std的情况下支持不合格的开始/结束调用; 或者使用std :: begin;?
我有一个类,我们称之为ConstVector,它只定义cbegin/cend而不是begin/end,因为我不想在构造之后允许对其成员进行修改.我尝试使用基于for循环的范围,如下所示:
ConstVector const_vector(1, 2, 3);
for(const auto &x : const_vector)
....
Run Code Online (Sandbox Code Playgroud)
虽然该课程的相关部分如下所示:
template<class T>
class ConstVector
{
public:
ConstVector(std::initializer_list<T> values);
typename std::vector<T>::const_iterator cbegin(void) const;
typename std::vector<T>::const_iterator cend(void) const;
private:
std::vector<T> data;
};
template<class T>
ConstVector::ConstVector(std::initializer_list<T> values)
: data(values)
{
}
template<class T>
typename std::vector<T>::const_iterator ConstVector<T>::cbegin() const
{
return this->data.cbegin();
}
template<class T>
typename std::vector<T>::const_iterator ConstVector<T>::cend() const
{
return this->data.cend();
}
Run Code Online (Sandbox Code Playgroud)
但我的编译器抱怨:
‘begin’ was not declared in this scope
Run Code Online (Sandbox Code Playgroud)
我的问题是:我必须实现开始/结束吗?据我所知,它应该选择cbegin/cend,如果它const auto &x不是auto &x.至少这对我来说是有意义的.如果我删除基于for循环的范围,一切都编译得很好.
我也尝试过这里提出的所有内容const …