And*_*rey 182 c++ iterator const-correctness const-iterator c++11
我想知道为什么cbegin
并cend
在C++ 11中引入?
什么情况下使用这些方法时,使得从常量重载的差异begin
和end
?
Nic*_*las 220
这很简单.说我有一个矢量:
std::vector<int> vec;
Run Code Online (Sandbox Code Playgroud)
我填写了一些数据.然后我想得到一些迭代器.也许传递给他们.也许到std::for_each
:
std::for_each(vec.begin(), vec.end(), SomeFunctor());
Run Code Online (Sandbox Code Playgroud)
在C++ 03中,SomeFunctor
可以自由修改它获得的参数.当然,SomeFunctor
可以通过值或通过获取其参数const&
,但是没有办法确保它的确如此.不是没有像这样愚蠢的事情:
const std::vector<int> &vec_ref = vec;
std::for_each(vec_ref.begin(), vec_ref.end(), SomeFunctor());
Run Code Online (Sandbox Code Playgroud)
现在,我们介绍cbegin/cend
:
std::for_each(vec.cbegin(), vec.cend(), SomeFunctor());
Run Code Online (Sandbox Code Playgroud)
现在,我们有语法保证,SomeFunctor
不能修改向量的元素(当然没有const-cast).我们明确得到const_iterator
s,因此SomeFunctor::operator()
将被调用const int &
.如果它的参数为int &
,则C++将发出编译器错误.
C++ 17有一个更优雅的解决方案来解决这个问题:std::as_const
.好吧,至少在使用基于范围时它很优雅for
:
for(auto &item : std::as_const(vec))
Run Code Online (Sandbox Code Playgroud)
这只是将a返回const&
给它提供的对象.
Ste*_*sky 65
除了Nicol Bolas在他的回答中所说的,考虑新的auto
关键字:
auto iterator = container.begin();
Run Code Online (Sandbox Code Playgroud)
有了auto
,没有办法确保begin()
为非常量容器引用返回常量运算符.所以现在你做:
auto const_iterator = container.cbegin();
Run Code Online (Sandbox Code Playgroud)
Joh*_*itb 14
把它作为一个实用的用例
void SomeClass::f(const vector<int>& a) {
auto it = someNonConstMemberVector.begin();
...
it = a.begin();
...
}
Run Code Online (Sandbox Code Playgroud)
赋值失败,因为它it
是一个非对象迭代器.如果你最初使用了cbegin,迭代器就会有正确的类型.
来自http://www.open-std.org/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 ...
}
Run Code Online (Sandbox Code Playgroud)
但是,当容器遍历仅用于检查时,通常优选使用const_iterator以允许编译器诊断const-correctness违规
请注意,工作文件还提到了适配器模板,现在已经最终确定为std::begin()
,std::end()
并且也适用于本机阵列.相应的,std::cbegin()
并且std::cend()
在这个时候奇怪地丢失了,但是它们也可能被添加.
只是偶然发现了这个问题...我知道它已经被回答了,而且只是一个副节点...
auto const it = container.begin()
然后是另一种类型 auto it = container.cbegin()
的区别int[5]
(使用指针,我知道没有begin方法,但是很好地显示了区别...但是可以在c ++ 14中用于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
Run Code Online (Sandbox Code Playgroud)