std::array用.size()最安全,因其编译期固定、constexpr零开销;c风格数组和int*无内置长度,需外部传入或约定,sizeof仅在定义域内有效,跨函数即失效。

编译期知道长度的 std::array,用 .size() 最安全;运行期分配的 int* 或 C 风格数组,根本“没长度”可取,只能靠外部传入或约定。
std::array 怎么安全取长度
std::array 是模板容器,大小在编译期固定,所以它的 .size() 是 constexpr,零开销且类型安全。
- 必须用
.size(),别用sizeof除以元素大小——虽然数值可能碰巧对,但语义错误,且一旦换成指针就崩 -
std::array<int> a;</int>→a.size()返回5(类型是size_t),不是int - 不能对
std::array取地址后传给期望int*的函数再想“恢复长度”——类型信息已丢失
C 风格数组(如 int arr[10])为什么不能直接问长度
这类数组名在多数上下文中会隐式退化为指针,sizeof(arr) 只在定义作用域内有效;一旦传参、赋值或取地址,就只剩一个 int*,长度彻底不可知。
- 错误写法:
void f(int* p) { return sizeof(p); }→ 永远返回指针大小(通常是 8) - 正确做法:调用方显式传长度,例如
f(arr, sizeof(arr)/sizeof(arr[0])) - 宏
ARRAY_SIZE(x)(定义为sizeof(x)/sizeof((x)[0]))只在数组定义作用域内可用,进函数就失效
new 分配的动态数组(int* p = new int[n])怎么处理
C++ 标准不记录堆上数组的长度,delete[] 能释放是因为编译器在分配时额外存了元数据,但这个信息不对外暴露。
立即学习“C++免费学习笔记(深入)”;
- 绝不要试图通过指针反推长度——没有标准接口,不同编译器/平台行为不一致
- 实际项目中一律改用
std::vector,它封装了长度和内存管理:v.size()安全可靠 - 如果必须用裸指针(如对接 C API),长度必须由分配者保存并显式传递,比如用结构体打包:
struct Buf { int* data; size_t len; };
容易被忽略的坑:模板参数推导和 auto
用 auto 声明数组引用时,类型推导很关键;模板函数里若想接受任意大小的 std::array,得靠模板参数推导长度。
-
auto a = std::array{1,2,3};→ 推导为std::array<int></int>,a.size()正常 -
auto& ref = arr;(arr是 C 风格数组)→ref是数组引用,sizeof(ref)仍有效,但出作用域就悬空 - 模板函数要支持任意
std::array:template<size_t n> void f(const std::array<int n>& a) { a.size(); }</int></size_t>
最麻烦的永远是跨边界传递——C 风格数组进了函数、指针交给了别人、或者和 C 库混用时,长度信息就像泼出去的水,收不回来。这时候硬要“获取”,不如回头检查接口设计是否漏了长度参数。











