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

时间:2013-03-25 19:50:03

标签: c++ c++11 iterator initializer-list

如果std::initializer_list中的元素始终是const值,为什么我们有begin()/end()而不是cbegin()/cend()等模板方法?这些名称(根据惯例,与std::vector进行比较)可能表明std::initializer_list方法在返回iterator时都会返回const_iterator

1 个答案:

答案 0 :(得分:25)

虽然除了 {{{{}}之外,我无法提供cbegin()cend()不属于std::initializer_list的界面的原因的见解1}}和begin(),最后两个成员函数应该存在的原因当然有很好的理由。

例如,一个原因是基于范围的end()循环是由C ++ 11标准精确定义的函数forbegin()(第6.5段)。 4/1)。因此,为了能够将其与初始值设定项列表一起使用,end()必须提供std::initializer_listbegin()成员函数:

end()

此外,考虑在C ++ 11之前不存在成员函数#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 << " "; } } cbegin()是有意义的:因此,在接口上有cend()begin() end()允许使用std::initializer_listbegin()编写的旧通用算法也可以使用初始化列表,而不需要重写它们。

你写道:

  

这些名称(根据惯例,与end()进行比较)可能表明std::vector方法在返回std::initializer_list时都会返回iterator

实际上,这个类比并不合适。例如,const_iterator的函数std::vectorbegin()的非iterator实例上调用时返回const(即一个可变的实例,其元素可以修改,添加和删除),并在std::vector实例上调用const_iterator(即不可更改的实例,其内容不能更改):

const
根据定义,

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

  

类型为#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?"); } 的对象提供对initializer_list<E>类型对象数组的访问。 [...]

由于初始化列表是const E个元素的集合,constcbegin()函数实际上与cend()begin()完全相同。

实际上,end()iterator都被定义为指向初始化列表的值类型的常量元素的指针,因此可以说是const_iterator和{{1}的情况总是返回begin()(如您所愿),或者它们是否总是返回end()

这就是C ++ 11标准的第18.9 / 1段如何定义const_iterator类模板:

iterator