C++标准是否保证std::equal遇到首个不匹配时短路终止?
你用于比较nul结尾字符串和字符串字面量的代码如下:
#include <algorithm> bool is_foo(const char *str) { const char *lit = "foo"; return std::equal(lit, lit + 4, str); }
结论
这段代码在所有正式发布的C++标准下都是良定义行为,不会触发未定义内存访问。
标准依据
C标准从首个标准化版本(C98)开始,对std::equal的执行规则就有明确约束:
- 算法按迭代器递增顺序逐对比较两个范围的对应元素,一旦遇到第一对不相等的元素,立刻终止比较返回
false,不会访问两个范围中后续位置的元素。 - 复杂度要求明确规定:算法最多执行
last1 - first1次元素相等判断,不存在多余的内存访问操作。 - 只有当所有比较过的元素全部相等时,算法才会遍历完第一个输入范围的全部元素,返回
true。
针对这段代码的场景,不存在越界访问的可能,所有运行情况都可以得到明确的行为定义:
- 当
str和"foo"完全匹配时:4个比较位置的元素依次是'f'、'o'、'o'、'\0',全部相等返回true。此时str的第4个元素(索引3)是'\0',说明str的合法可访问长度至少为4,完全满足三参数std::equal对第二个范围的长度要求,没有越界。 - 当
str长度小于4、前缀部分匹配时:比如str是空串、"f"、"fo"这类短字符串,比较到第一个不相等的位置时就会终止。比如str = "fo"时,比较到第3个元素(索引2),字面量侧是'o',str侧是终止符'\0',两者不相等立刻返回,全程只访问str前3个字节的合法内存,不会触碰后续越界位置。 - 当
str长度任意但内容不匹配时:在第一个不匹配的位置就会终止比较,不会出现越界。
补充说明:开发者常提到的三参数
std::equal越界风险是真实存在的——如果传入的第二个范围实际长度小于第一个范围,且两个范围的前N个元素(N等于第二个范围长度)完全相等,算法会继续访问第二个范围之后的越界内存触发未定义行为。但这段代码通过把字面量的终止符\0纳入比较范围,天然规避了这个场景:只要算法真的遍历完4个元素,就说明str的第4个位置也是\0,str长度必然满足要求,不存在越界可能。
内容的提问来源于stack exchange,提问作者ridiculous_fish
相关产品推荐
相关产品推荐

