【Effective Modern C++】第三章 转向现代C++:13. 优先选用const_iterator,而非iterator

STL 的const_iterator等价于 "指向常量的指针(pointer-to-const)",指向的值不可修改,符合 "能加const就加" 的通用编程准则 ------ 只要无需修改迭代器指向的值,就应优先使用const_iterator;但该迭代器的实用性随 C++ 版本迭代大幅提升,C++11 是关键转折点,同时通用代码中需优先使用非成员函数版本的begin/end/cbegin等。

各 C++ 版本对 const_iterator 的支持差异

1. C++98:支持残缺,实用性差

const_iterator理论上符合规范,但实际使用存在两大痛点:

  • 创建麻烦 :非const容器无法直接获取const_iterator,需强制类型转换(或绑定到const引用)才能得到;

  • 使用受限insert/erase等容器操作仅接受iterator,且const_iterator无法可移植转换为iterator(即使reinterpret_cast也不行);

    最终导致开发者被迫放弃使用,违背 "能constconst" 的准则。

c++ 复制代码
typedef std::vector<int>::iterator IterT; 
typedef std::vector<int>::const_iterator ConstIterT; 

std::vector<int> values; 
... 
// 非const容器需强制转换才能获取const_iterator 
ConstIterT ci = 
	std::find(static_cast<ConstIterT>(values.begin()), 
			  static_cast<ConstIterT>(values.end()), 
			  1983); 
// insert不接受const_iterator,转换iterator也无可靠方法(编译失败) 
values.insert(static_cast<IterT>(ci), 1998);

C++11:支持完善,易用性大幅提升

解决了 C++98 的核心痛点,让const_iterator真正实用:

  • 容器新增cbegin/cend成员函数,非const容器也能直接获取const_iterator

  • insert/erase等操作支持接收const_iterator,无需转换即可使用;

    示例:无需修改迭代器指向值的查找 + 插入场景,可直接用cbegin/cend获取const_iterator,代码简洁且符合规范。

c++ 复制代码
std::vector<int> values; 
... 
// 直接用cbegin/cend获取const_iterator,insert原生支持 
auto it = std::find(values.cbegin(), values.cend(), 1983); 
values.insert(it, 1998);

C++11 的小缺陷与 C++14 的补全

  • C++11 仅新增非成员函数begin/end,缺失cbegin/cend/rbegin/rend等;
  • C++14 补全了这些非成员函数,满足 "最大程度通用的库代码" 需求(适配原生数组、仅提供自由函数接口的第三方库等)。

通用代码的适配方案(C++11 兼容)

若 C++11 环境下 STL 未提供非成员cbegin等函数,可自行实现(兼容普通容器和原生数组):

  • 核心逻辑:通过const引用接收容器 / 数组,调用 C++11 提供的非成员begin------ 对const容器 / 数组,begin会自动返回const_iterator(数组场景下等价于指向const的指针);
  • 无需依赖容器的cbegin成员函数,适配性更强。

总结

  • 优先选用const_iterator,而非iterator
  • 在最通用的代码中,优先选用非成员函数版本的beginendrbegin等,而非其成员函数版本。

原著在线阅读地址

相关推荐
光电笑映几秒前
C++11 新特性全解:语法糖、容器进化与可调用对象包装
开发语言·c++
SWAGGY..13 分钟前
【C++初阶】:(7)STL简介
开发语言·c++
6Hzlia36 分钟前
【Hot 100 刷题计划】 LeetCode 279. 完全平方数 | C++ 动态规划 (完全背包)
c++·leetcode·动态规划
H Journey42 分钟前
C++ 11 新特性 统一初始化与与 std::initializer_list
c++·列表初始化
木子墨5161 小时前
LeetCode 热题 100 精讲 | 动态规划进阶篇:最大子数组和 · 分割等和子集 · 最长公共子序列 · 打家劫舍 III
数据结构·c++·算法·leetcode·动态规划·力扣
li1670902701 小时前
第十章:list
c语言·开发语言·数据结构·c++·算法·list·visual studio
‎ദ്ദിᵔ.˛.ᵔ₎1 小时前
仿函数使用
c++
Z1Jxxx1 小时前
C++ P1150 Peter 的烟
数据结构·c++·算法
是娇娇公主~1 小时前
线程池:工作窃取线程池WorkingStealingPool
c++·线程池
CheerWWW1 小时前
C++学习笔记——函数指针、Lambda表达式、谨慎使用using namespace std、命名空间
c++·笔记·学习