不使用临时变量交换变量时出现警告错误的原因是什么?
关于C++交换变量时触发
-Wsequence-point警告的原因解析 嘿,这个问题我当初刚学C++的时候也踩过坑!咱们来一步步搞清楚为啥编译器会给你抛出这个警告。
首先先把你的代码贴出来方便分析:
{ int right = 5, left = 14; std::cout << right << " " << left << std::endl; right = right + left - (left = right); std::cout << right << " " << left << std::endl; }
核心原因:序列点(Sequence Point)与未定义行为
C++标准里有个关键规则:在两个序列点之间,同一个对象不能被修改超过一次,同时也不能在修改后未经序列点就读取该对象的值。
那回到你的代码里的这行关键代码:right = right + left - (left = right);
这里面发生了什么?我们拆解一下:
- 你在同一个表达式里,先尝试读取
left的值(用于计算right + left),然后又在括号里修改了left的值(left = right)。 - 这两个操作(读取
left和修改left)之间没有任何序列点。
序列点是什么?简单说就是编译器保证前面的操作都执行完,后面的操作才会开始的“节点”,比如分号、逗号运算符(注意不是函数参数里的逗号分隔符)、逻辑与/或的短路触发点等等。而你的这行赋值表达式里,整个式子只有一个序列点(就是最后的分号),在这之前的所有子表达式的执行顺序是编译器说了算的!
这就导致了未定义行为:
- 如果编译器先计算
right + left(此时left还是14),再执行left = right(left变成5),最后计算19 - 5 = 14,right变成14,结果是交换成功的; - 但如果编译器先执行
left = right(left先变成5),再计算right + left(此时是5+5=10),最后10-5=5,right变成5,结果是两个变量都变成5,完全不符合你的预期。
编译器就是发现了这种“执行顺序不确定,结果不可靠”的情况,才抛出了operation on ‘left’ may be undefined的警告,提醒你这个代码的行为是不可预测的。
安全的无临时变量交换方式
如果想不用临时变量交换,推荐这些有定义的写法:
- 异或法(注意:仅适用于整数类型,且两个变量不能指向同一个内存地址):
left ^= right; right ^= left; left ^= right; - C++11及以后的结构化绑定写法:
std::tie(left, right) = std::make_tuple(right, left); - 当然,最稳妥的还是直接用标准库的
std::swap:std::swap(left, right);
内容的提问来源于stack exchange,提问作者Programming Lover
相关产品推荐
相关产品推荐

