简体   繁体   English

begin()和end()函数不应该是模板类Vector的成员函数吗?

[英]Shouldn't the begin() and end() functions be member functions of the template class Vector?

In page 82 of the draft of Chapter 3 : A Tour of C++: Abstraction Mechanisms the author writes: 在第3章:C ++之旅:抽象机制草案的第82页中 ,作者写道:

If we also want to use the range-for loop for our Vector , we must define suitable begin() and end() functions: 如果我们还想对Vector使用range-for循环,则必须定义合适的begin()end()函数:

template<typename T>
T∗ begin(Vector<T>& x)
{
    return &x[0]; // pointer to first element
}

template<typename T>
T∗ end(Vector<T>& x)
{
    return x.begin()+x.size(); // pointer to one-past-last element
}

Given those, we can write: 有了这些,我们可以写:

void f2(const Vector<string>& vs) // Vector of some strings
{
    for (auto s : vs)
        cout << s << ’\n’;
}

Notice that the class template Vector is defined in page 81 of the draft. 请注意,类模板Vector在草稿的第81页中定义。

For range-based for to work, the compiler needs to find a suitable function to get the iterators. 为了使基于范围的工作正常,编译器需要找到合适的函数来获取迭代器。

  • If the type used is a class, it'll first look for member functions begin and end in the scope of that class. 如果使用的类型是类,则它将首先查找成员函数,该函数在该类的范围内beginend

  • If the type is not a class or the are no such member functions, it looks them up by Argument Dependent Lookup. 如果类型不是类或没有此类成员函数,则通过“ 参数依赖查找”查找它们。

This is the reason range-based for works on C-arrays. 这就是基于范围进行C阵列工作的原因。 Obviously, arrays can't have member functions, so standard library provides two functions defined similarly to this: 显然,数组不能具有成员函数,因此标准库提供了两个与此定义类似的函数:

template<typename T, size_t N>
T* begin( T(&array)[N] )
{
    return array;
}

and similarly for end . 同样地end

To answer your question from the title: they can be, but it's not a neccesity. 从标题回答您的问题: 可以 ,但不是必须的。 You can define free functions in the same namespace as your class and they'll be found. 您可以在与类相同的名称空间中定义自由函数,然后就会找到它们。

If it is not an array or a container with .begin() and .end() it will look up by Argument dependent name . 如果它不是具有.begin().end()的数组或容器,则将通过依赖参数的name查找。

It is said here : 据说这里

Keep in mind these facts about range-based for: 请记住以下有关基于范围的事实:

  • Automatically recognizes arrays. 自动识别数组。

  • Recognizes containers that have .begin() and .end(). 识别具有.begin()和.end()的容器。

  • Uses argument-dependent lookup begin() and end() for anything else. 使用依赖于参数的查找begin()和end()进行其他操作。

In such a range based for: 在这样的范围内基于:

for ( for-range-declaration : expression ) statement

the standard says that the compiler looks for either members ( (expression).begin() , (expression).end() ) or free functions ( begin((expression)) , end((expression)) ) if expression is of class type. 标准说,如果expression是类,则编译器将查找成员( (expression).begin()(expression).end() )或自由函数( begin((expression))end((expression)) )。类型。

Therefore you can either provide member functions OR free functions (which need to be in scope for argument dependant lookup). 因此, 您既可以提供成员函数,也可以提供自由函数 (这些函数必须在依赖于参数的查找范围内)。

C++11, § 6.5.4 [stmt.ranged] C ++ 11,第6.5.4节[stmt.ranged]

This is what a ranged-based for does according to the standard: 这是基于标准的基于范围的操作:

for ( for-range-declaration : expression ) statement

range-init = ( expression )

{
  auto && __range = range-init;
  for ( auto __begin = begin-expr,
    __end = end-expr;
    __begin != __end;
    ++__begin ) 
  {
    for-range-declaration = *__begin;
    statement
  }
}

The begin-expr and end-expr are described as: begin-exprend-expr描述为:

  • if _RangeT is an array type, begin-expr and end-expr are _ range and 如果_RangeT是数组类型,则begin-exprend-expr_ range _range + _ bound , respectively, where _range + _ bound ,其中 _bound is the array bound. _bound是数组绑定。 If _RangeT is an array of unknown size or an array of incomplete type, the program is ill-formed; 如果_RangeT是未知大小的数组或类型不完整的数组,则程序格式错误

  • if _RangeT is a class type, the unqualified-ids begin and end are looked up in the scope of class _RangeT as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, beginexpr and end-expr are __range.begin() and __range.end(), respectively; 如果_RangeT是类类型,则在_RangeT类的范围内查找不合格ID的begin和end,就像通过类成员访问查找(3.4.5)一样,并且如果一个(或两个)都找到至少一个声明,则beginexpr和end-expr分别是__range.begin()和__range.end();

  • otherwise, begin-expr and end-expr are begin(__range) and end(__range) , respectively, where begin and end are looked up with argument-dependent lookup (3.4.2). 否则, begin-exprend-expr分别是begin(__range)end(__range) ,其中beginend是通过与参数相关的查找(3.4.2)查找的。 For the purposes of this name lookup, namespace std is an associated namespace. 出于此名称查找的目的,名称空间std是关联的名称空间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM