
std::string 用 size() 或 length(),别用 sizeof
很多人一上来就写 sizeof(str),结果得到 24 或 32 —— 这是 std::string 对象本身的大小,不是里面存的字符数。它内部用指针管理堆上内存,sizeof 根本不看内容。
正确做法就是调 size() 或 length(),这两个完全等价,都是 O(1) 时间查内部计数器:
std::string s = "hello"; std::cout << s.size(); // 输出 5 std::cout << s.length(); // 输出 5,一样
- 别对
std::string用c_str()再算strlen,多此一举还慢 - 如果字符串含 '\0'(比如从二进制数据构造),
size()仍返回真实字节数;strlen会提前截断 - 空字符串
""的size()是 0,不是 1
C 风格字符串必须用 strlen(),不能依赖 sizeof
char arr[] = "abc" 看似简单,但 sizeof(arr) 返回的是整个数组字节数(包括末尾 '\0'),而 strlen(arr) 才是真正“长度”——即 '\0' 前的字符个数。
常见错误是把栈上数组传给函数后还用 sizeof:
立即学习“C++免费学习笔记(深入)”;
void bad_func(char s[]) {
std::cout << sizeof(s); // 错!这里 s 是 char*,sizeof 永远是 8(64 位系统)
}- 函数参数写成
char s[]和char* s完全等价,数组退化为指针 - 只有在定义数组的同一作用域内,
sizeof(arr)才有效,且结果包含 '\0' -
strlen()遇到第一个 '\0' 就停,所以确保 C 字符串以 '\0' 结尾,否则行为未定义
原生数组长度只能靠 sizeof(arr)/sizeof(arr[0]),且仅限定义处
这是唯一能从数组变量本身推导长度的办法,但有严格限制:只在数组定义的作用域里有效,不能跨函数、不能用于指针。
int arr[] = {1, 2, 3, 4};
std::cout << sizeof(arr) / sizeof(arr[0]); // 输出 4- 一旦写成
int* p = arr;,sizeof(p)就变成指针大小,除法毫无意义 - 模板函数里可以用
std::size()(C++17 起)或std::extent_v,但本质还是编译期推导,不适用于运行时动态大小 - 如果数组元素类型是类,
sizeof(arr[0])必须准确,别误写成sizeof(int)这类硬编码
std::array 和 std::vector 用 size() 最省心
它们都提供标准的 size() 成员函数,语义统一、安全、高效,不用记例外规则。
std::array<int, 5> a = {1,2,3,4,5};
std::vector<char> v = {'h','e','l','l','o'};
std::cout << a.size(); // 5
std::cout << v.size(); // 5-
std::array的size()是 constexpr,编译期可知;std::vector是运行时值 - 别混淆
std::vector::capacity()和size():前者是已分配内存能容纳多少,后者才是当前元素个数 - 所有标准容器(
std::list、std::deque等)都支持size(),但std::forward_list是例外,它没有 O(1) size,得用std::distance
C++ 里“长度”不是单一概念,它取决于你手上拿的是什么类型、在哪一作用域、是否可变。最危险的坑就是把数组和指针当成一回事,或者把对象大小和逻辑长度混为一谈。写的时候多问一句:这个变量此刻在内存里到底是块连续区域,还是个指针,还是个封装好的对象?










