条款13.优先选用const_iterator,而非iterator

优先选择const_iterator,而非iterator

const_iterator在STL中相当于指向const的指针。它们指向不可被修改的值,只有由可能就应该使用const

任何时候只要你需要一个迭代器而其指向的内容没有修改必要,就应该使用const_iterator

在C++11中,获取和使用const_iterator变得很容易,容器的成员函数cbegin()cend()都返回const_iterator类型,甚至对于非const容器也是如此,并且STL成员函数若要取用指示位置的迭代器(例如插入或删除),它们也要求使用const_iterator类型

std::vector<int> values;
...
auto it = std::find(values.cbegin(), values.cend(), 1983);
values.insert(it, 1998);

在撰写最通用化的库代码时,某些容器,或类似容器的数据结构会以非成员函数的方式提供beginend,而不是成员函数方式。

举例来说,刚才写的代码可以写成下面findAndInsert模板的通用形式

template<typename C,typename V>
void findAndInsert(C& container,
                  const V& targetVal,
                  const V& insertVal)
{
    using std::cbegin;
    using std::cend;
    
    auto it = std::find(cbegin(container),cend(container), targetVal);
    container.insert(it, insertVal);
}

以上代码在C++14中可以完全正常运行,在C++11中却不行。C++11仅添加了非成员版本的beginend,而没有添加cbegincendrbeginrendcrbegincrend

如果使用的是C++11,而且要撰写最通用化的代码,但使用的库中却没有提供成员函数版本的cbein系列缺失的模板。可以很容易地写出你自己的实现。

下面是非成员函数版本的cbegin的一个实现

template<class C>
auto cbegin(const C& container)->decltype(std::begin(container))
{
    return std::begin(container);
}

这个cbegin接受一个形参C,实参类型可以是任何表示类似容器的数据结构,并通过其引用到const类型的形参container来访问该实参。如果C对应一个传统容器类型(例如,std::vector<int>),则container就是该容器类型的引用到const的版本(例如,const std::vector<int>&)。调用非成员函数版本的begin函数并传入一个const容器会产生一个const_iterator,而模板返回的正是这个迭代器。这样实现的好处是它对于那些只提供了begin成员函数而未提供cbegin成员函数的容器也适用。

该模板在C是一个内建数组时也适用。在这种情况下,container成为了一个const数组的引用,C++11的非成员函数版本的begin为数组提供了一个特化版本,它返回一个指向数组首元素的指针。由于const数组的元素都是const,所以若给非成员函数版本的begin传入一个const数组,则其返回的指针是个指向const的指针。

要点速记

  • 优先选择const_iterator,而非iterator
  • 在最通用的代码中,优先选择非成员函数版本的beginendrbegin等,而非其成员函数版本
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值