为何比较C风格字符串的vector时std::equal返回值有差异?
std::equal在不同const char*容器场景下返回值差异的原因解析
问题背景
请解释为何在以下三种场景中,尽管输出的vector元素存储地址均不相同,std::equal函数的返回值却有时为true、有时为false:
- 场景一:直接使用字符串字面量初始化
std::vector<const char*>,调用std::equal返回true,但输出的vector中元素的存储地址并不相等。 - 场景二:通过C风格字符串指针数组初始化vector,
std::equal仍返回true,元素存储地址依旧不同。 - 场景三:通过二维字符数组初始化vector,此时
std::equal返回false,元素存储地址同样不同。
测试代码:
#include <iostream> #include <vector> #include <algorithm> #include <numeric> int main() { std::cout << std::boolalpha; std::vector<const char*> vec_e{ "String" }; std::vector<const char*> vec_f{ "String" }; std::cout << equal(vec_e.begin(), vec_e.end(), vec_f.begin()) << std::endl; // true std::cout << &vec_e[0] << std::endl; std::cout << &vec_f[0] << std::endl; const char* str_a[1] = { "Hello" }; const char* str_b[1] = { "Hello" }; std::vector<const char*> vec_a(std::begin(str_a), std::end(str_a)); std::vector<const char*> vec_b(std::begin(str_b), std::end(str_b)); std::cout << equal(vec_a.begin(), vec_a.end(), vec_b.begin()) << std::endl; // true std::cout << &vec_a[0] << std::endl; std::cout << &vec_b[0] << std::endl; const char str_c[][6] = { "World" }; const char str_d[][6] = { "World" }; std::vector<const char*> vec_c(std::begin(str_c), std::end(str_c)); std::vector<const char*> vec_d(std::begin(str_d), std::end(str_d)); std::cout << equal(vec_c.begin(), vec_c.end(), vec_d.begin()) << std::endl; // false std::cout << &vec_c[0] << std::endl; std::cout << &vec_d[0] << std::endl; return 0; }
核心前提
首先要明确两个关键概念:
std::equal默认行为是逐元素调用==运算符进行比较,这里的元素类型是const char*,所以比较的是指针的值(即指向的内存地址),而非字符串内容。- 代码中
std::cout << &vec_e[0] << std::endl;输出的是vector容器内存储的指针变量本身的地址,而非指针指向的字符串/数组的内存地址,这是容易混淆的点。
场景一与场景二的原因(返回true)
这两个场景的本质完全一致:
- 字符串字面量(如
"String"、"Hello")会被编译器放在程序的只读数据段,并且编译器会启用字符串字面量池优化——相同内容的字符串字面量会被合并为同一个内存实例,避免重复存储。 - 场景一中,
vec_e[0]和vec_f[0]这两个指针,实际上指向的是同一个字符串字面量的内存地址;场景二中,str_a[0]和str_b[0]同理,指向同一个字面量地址,vector初始化后继承了这个指针值。 std::equal比较的是这些指针的值(指向的字符串地址),值相等所以返回true;而代码输出的&vec_e[0]是vector内部存储指针的地址,两个vector是独立对象,所以这个地址自然不同。
场景三的原因(返回false)
const char str_c[][6] = { "World" };定义的是二维字符数组,str_c[0]是一个长度为6的字符数组(存储"World"加终止符'\0'),它的内存是独立分配的;同理str_d[0]是另一个完全独立的字符数组,两者在内存中的位置不同。- 初始化vector后,
vec_c[0]是str_c[0]的首地址,vec_d[0]是str_d[0]的首地址,这两个指针的值(指向的数组地址)完全不同。 std::equal比较这两个指针的值,结果不相等,所以返回false;代码输出的&vec_c[0]同样是vector内部指针的存储地址,和另一个vector的对应地址自然不同。
内容的提问来源于stack exchange,提问作者iamnotevg
相关产品推荐
相关产品推荐

