一、RANGE-BASED FOR 到底发生了什么?
表面代码
编译器展开(标准定义)
auto&& r=R;for(auto it=begin(r);it!=end(r);++it){T x=∗it;F(x);}\begin{aligned} &\text{auto\&\& }r=R;\\ &\text{for(auto it=begin(r);it!=end(r);++it)}\{ & \quad T\ x=*it;\\ & \quad F(x);\\ &\} \end{aligned} auto&& r=R;for(auto it=begin(r);it!=end(r);++it){F(x);} T x=∗it;
关键点解释
行 含义 auto&& r=R 万能引用,保留左值 / 右值 begin(r)/end(r) 非成员或成员 begin T x=*it 每次都会构造一次 x
这就是为什么:
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
二、结构化绑定(STRUCTURED BINDING)内部机制
最基础例子
实际发生的事(逻辑展开)
设:
p=(k0,v0)p=(k_0,v_0) p=(k0 ,v0 )
则等价于:
auto&& t=p;alias k≡getlt;0gt;(t);alias v≡getlt;1gt;(t);\begin{aligned} &\text{auto\&\& }t=p;\\ &\text{alias }k\equiv\text{get}<0>(t);\\ &\text{alias }v\equiv\text{get}<1>(t); \end{aligned} auto&& t=p;alias k≡getalias v≡get lt;0lt;1 gt;(t);gt;(t);
不是声明两个变量,而是两个别名
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
三、RANGE FOR + STRUCTURED BINDING 联合展开
MAP 遍历的完整真相
展开成数学形式
∀(ki,vi)∈m:vi←vi+1\forall (k_i,v_i)\in m:\quad v_i\leftarrow v_i+1 ∀(ki ,vi )∈m:vi ←vi +1
编译器视角
所以:
* k 是引用
* v 是引用
* 修改 v 就是修改 map
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
四、为什么必须用 AUTO& 才能改?
错误示例
原因公式
vlocal≠vmapv_{\text{local}}\neq v_{\text{map}} vlocal =vmap
因为:
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
五、CONST 的正确打开方式
类型关系
decltype(k)=const Key&decltype(v)=const Value&\begin{aligned} &\text{decltype}(k)=\text{const Key\&}\\ &\text{decltype}(v)=\text{const Value\&} \end{aligned} decltype(k)=const Key&decltype(v)=const Value&
所以:
* 可以读
* 不能写
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
六、STRUCT / TUPLE / ARRAY 的统一规则
STRUCT
等价于:
(a,b)=(p.x, p.y)(a,b)=(\text{p.x},\ \text{p.y}) (a,b)=(p.x, p.y)
限制:
* 所有成员必须是 public
* 不能混合 private/public
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TUPLE
(i,j,k)=(t0,t1,t2)(i,j,k)=(t_0,t_1,t_2) (i,j,k)=(t0 ,t1 ,t2 )
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ARRAY
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
七、常见错误逐条解析
1. 绑定数量不一致
#vars≠#elements⇒compile error\#\text{vars}\neq\#\text{elements}\Rightarrow\text{compile error} #vars=#elements⇒compile error
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2. CONST 对象被修改
const⇒immutable\text{const}\Rightarrow\text{immutable} const⇒immutable
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3. MAP KEY 被修改(危险)
map 的 key 本质是:
decltype(k)=const Key&\text{decltype}(k)=\text{const Key\&} decltype(k)=const Key&
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
八、什么时候不该用结构化绑定?
场景 建议 只用一个成员 不用绑定 逻辑复杂 显式写 调试困难 不用 私有成员 不能用
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
九、最终速记公式(考试 / 面试)
map遍历⇒for(auto&[k,v]:m)只读⇒const auto&结构化绑定≠新变量是引用别名\boxed{ \begin{aligned} &\text{map遍历}\Rightarrow\texttt{for(auto\&[k,v]:m)}\\ &\text{只读}\Rightarrow\texttt{const auto\&}\\ &\text{结构化绑定}\neq\text{新变量}\\ &\text{是引用别名} \end{aligned} } map遍历⇒for(auto&[k,v]:m)只读⇒const auto&结构化绑定=新变量是引用别名
十、注意:C++17 及以上
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
求赞