C++17中if条件内函数调用里赋值是否为定义行为?
C++17中短路赋值写法的行为定义分析
这种写法的行为在C17中是完全有定义的,核心依据是C标准里的短路求值规则:逻辑或运算符||会先严格求值左侧操作数,只有当左侧结果为false时,才会继续求值右侧操作数。这个规则并非C17新增,在更早的C标准(如C11、C03)中就已经存在。
两段代码的具体行为分析
第一段:std::map版本
void myFunction (std::map<int, int> my_map) { int linked_element; if (my_map[linked_element = firstIndex] != 0 || my_map[linked_element = secondIndex] != 0) { // do some stuff with linked_element } }
执行顺序严格遵循短路规则:
- 先执行
linked_element = firstIndex,完成赋值 - 调用
std::map::operator[]:如果firstIndex不存在于map中,会自动插入一个值为0的元素 - 判断返回值是否不等于
0:- 若为
true,整个条件成立,右侧的赋值和map访问完全不会执行,linked_element的值是firstIndex - 若为
false,才会执行右侧的linked_element = secondIndex,重复上述map访问和判断逻辑
- 若为
第二段:std::set版本
void myFunction (std::set<int> my_set) { int linked_element; if (my_set.find(linked_element = firstIndex) != my_set.end() || my_set.find(linked_element = secondIndex) != my_set.end()) { // do some stuff with linked_element } }
逻辑类似但不会修改容器:
- 先执行
linked_element = firstIndex - 调用
std::set::find查找该值:- 若找到(迭代器不等于
end()),条件成立,右侧代码不执行,linked_element值为firstIndex - 若未找到,才会执行右侧的赋值和查找操作
- 若找到(迭代器不等于
关于写法的合理性
虽然行为有定义,但这种写法可读性极差,维护者很容易忽略条件判断中嵌有赋值操作,后续修改时极易引入bug。更清晰的替代写法应该将赋值与判断逻辑拆分:
比如std::set的C++17兼容写法:
void myFunction(std::set<int> my_set) { int linked_element; auto it = my_set.find(firstIndex); if (it != my_set.end()) { linked_element = firstIndex; } else { it = my_set.find(secondIndex); if (it != my_set.end()) { linked_element = secondIndex; } else { return; } } // do some stuff with linked_element }
对于std::map,如果不想自动插入不存在的键,应该用find代替operator[],避免不必要的容器修改:
void myFunction(std::map<int, int> my_map) { int linked_element; auto it = my_map.find(firstIndex); if (it != my_map.end() && it->second != 0) { linked_element = firstIndex; } else { it = my_map.find(secondIndex); if (it != my_map.end() && it->second != 0) { linked_element = secondIndex; } else { return; } } // do some stuff with linked_element }
内容的提问来源于stack exchange,提问作者f222
相关产品推荐
相关产品推荐

