没有cbegin()/ cend()的std :: initializer_list

Nie*_*eru 21 c++ iterator initializer-list c++11

如果元素std::initializer_list总是const值,为什么我们有模板方法喜欢begin()/end()和不cbegin()/cend()?这个名称(通过惯例,与例如比较std::vector)可以表明,当它们总是返回时,两种std::initializer_list方法都可以iterator返回const_iterator.

And*_*owl 25

虽然除了之外我无法提供有关其原因cbegin()cend()不属于std::initializer_list界面的原因的见解,因此有充分的理由说明为什么最后两个成员函数应该存在. begin()end()

例如,一个原因是,基于范围的for循环由C++ 11标准精确地根据函数begin()end()(第6.5.4/1段)定义.因此,为了能够将它与初始化列表一起使用,std::initializer_list必须提供begin()end()成员函数:

#include <utility>
#include <iostream>

int main()
{
    auto l = { 1, 2, 3, 4, 5 };
    for (int x : l) // Works because std::initializer_list provides
                    // the member functions begin() and end().
    {
        std::cout << x << " ";
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,是有意义的考虑成员函数cbegin()cend()不存在前C++ 11:因此,具有begin()end()的界面上std::initializer_list允许作出书面来讲旧通用算法begin()end()与初始化列表工作,以及,而不需要他们是重写.

你写:

这些名称(通过惯例,与例如比较std::vector)可以表明,当它们总是返回时,两种std::initializer_list方法都可以iterator返回const_iterator.

实际上,这个比喻不太合适.例如,std::vector函数在非实例(即可变元素,其元素可以被修改,添加和删除)上调用时返回,并且在实例上调用时(即不可变的实例,其内容)不能改变):begin()iteratorconststd::vectorconst_iteratorconst

#include <vector>
#include <type_traits>

int main()
{
    // A non-const vector...
    std::vector<int> v = { 1, 2, 3, 4, 5 };

    auto i = v.begin();
    static_assert(
        std::is_same<decltype(i), decltype(v)::iterator>::value, 
        //                                     ^^^^^^^^
        //                                     ...non-const iterator!
        "What?");

    // A const vector...
    std::vector<int> const vc = { 1, 2, 3, 4, 5 };
    auto ic = vc.begin();
    static_assert(
        std::is_same<decltype(ic), decltype(vc)::const_iterator>::value,
        //                                       ^^^^^^^^^^^^^^
        //                                       ...const iterator!
        "What?");
}
Run Code Online (Sandbox Code Playgroud)

根据定义,初始化程序列表是不可变集合.根据C++ 11标准的第18.9/2段:

类型的对象initializer_list<E>提供对类型对象数组的访问const E.[...]

由于初始化列表是集合const的元素,在cbegin()cend()功能实际上会做同样的事情,begin()而且end()做.

事实上,iteratorconst_iterator都定义为指针初始化列表中的值类型的常量元素,所以这是值得商榷的它是否是一个的情况下begin(),并end()总是返回const_iterator(如你假设),或者他们是否总是返回iterator.

这就是C++ 11 Standard的第18.9/1段定义initializer_list类模板的方式:

namespace std {
    template<class E> class initializer_list {
    public:
        typedef E value_type;
        // ...
        typedef const E* iterator;
        typedef const E* const_iterator;
        // ...
        constexpr const E* begin() const noexcept; // first element
        constexpr const E* end() const noexcept; // one past the last element
    };

    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • 我记得以前我曾经在SO上获得代表,但后来有人出现并以优秀的形式回答了所有优秀的C++问题.现在我只能投票.+1 (6认同)
  • @GManNickG:想想从第1天开始就被JonSkeeted的所有C#人. (2认同)