cbegin / cend背后的原因是什么?
我想知道为什么cbegin
和cbegin
是在C ++ 11中引入的?
什么情况下调用这些方法与const的重载begin
和end
什么不同?
这很简单。 说我有一个vector:
std::vector<int> vec;
我填写一些数据。 然后我想获得一些迭代器。 也许可以绕过他们。 也许是std::for_each
:
std::for_each(vec.begin(), vec.end(), SomeFunctor());
在C ++ 03中, SomeFunctor
可以自由地修改它获取的参数。 当然, SomeFunctor
可以通过值或const&
来接受它的参数,但是没有办法确保它的确如此。 不是没有做这样愚蠢的事情:
const std::vector<int> &vec_ref = vec; std::for_each(vec_ref.begin(), vec_ref.end(), SomeFunctor());
现在我们介绍一下cbegin/cend
:
std::for_each(vec.cbegin(), vec.cend(), SomeFunctor());
现在,我们有句法保证SomeFunctor
不能修改向量的元素(当然没有const-cast)。 我们明确地得到了const_iterator
,因此SomeFunctor :: operator()将会被const int &
调用。 如果将参数作为int &
,C ++将发出编译器错误。
C ++ 17有一个更优雅的解决scheme: std::as_const
。 那么,至less在使用基于范围的情况下,它是优雅for
:
for(auto &item : std::as_const(vec))
这只是返回一个const&
到它提供的对象。
除了尼古拉·布拉斯(Nicol Bolas)在他的回答中所说的,考虑一下新的auto
关键字:
auto iterator = container.begin();
对于auto
,没有办法确保begin()
为一个非常量容器引用返回一个常量运算符。 所以现在你做:
auto const_iterator = container.cbegin();
把这作为一个实际的用例
void SomeClass::f(const vector<int>& a) { auto it = someNonConstMemberVector.begin(); ... it = a.begin(); ... }
分配失败,因为it
是一个nonconst迭代器。 如果你最初使用cbegin,那么迭代器就会有正确的types。
从jtc1/sc22/wg21/docs/papers/2004/n1674.pdf :
所以程序员甚至可以从一个非const容器中直接获得一个const_iterator
他们给了这个例子
vector<MyType> v; // fill v ... typedef vector<MyType>::iterator iter; for( iter it = v.begin(); it != v.end(); ++it ) { // use *it ... }
然而,当一个容器遍历仅用于检查时,通常使用一个const_iterator来允许编译器诊断常量正确性违规
请注意,工作文件还提到了适配器模板,现在已经定稿为std::begin()
和std::end()
,并且也适用于本机数组。 std::cbegin()
,相应的std::cbegin()
和std::cbegin()
很好奇地丢失了,但是它们也可能被添加。
刚刚偶然发现了这个问题…我知道这是答案,它只是一个边节点…
auto const it = container.begin()
是一个不同的types,然后auto it = container.cbegin()
int[5]
的差别(使用指针,我知道没有开始的方法,但很好地显示差异…但将工作在C ++ 14为std::cbegin()
和std::cend()
std::cbegin()
std::cend()
,这本质上是在这里应该使用的)…
int numbers = array[7]; const auto it = begin(numbers); // type is int* const -> pointer is const auto it = cbegin(numbers); // type is int const* -> value is const
iterator
和const_iterator
具有inheritance关系,并且与其他types进行比较或分配时发生隐式转换。
class T {} MyT1, MyT2, MyT3; std::vector<T> MyVector = {MyT1, MyT2, MyT3}; for (std::vector<T>::const_iterator it=MyVector.begin(); it!=MyVector.end(); ++it) { // ... }
在这种情况下使用cbegin()
和cbegin()
会提高性能。
for (std::vector<T>::const_iterator it=MyVector.cbegin(); it!=MyVector.cend(); ++it) { // ... }