在 C++ 中,sizeof
是一个编译时运算符,用于计算对象或类型占用的内存大小(以字节为单位)。它既可用于基本类型、数组、结构体,也可用于类和指针。以下是 sizeof
的详细用法及关键注意事项:
一、sizeof
的基本用法
语法:
cpp
复制
sizeof(类型) // 直接指定类型 sizeof(表达式) // 根据表达式结果类型计算
示例 1:基本类型
cpp
复制
cout << sizeof(int) << endl; // 输出 4(常见平台) cout << sizeof(double) << endl; // 输出 8
示例 2:变量或对象
cpp
复制
int x = 10; double arr[5]; cout << sizeof(x) << endl; // 输出 4(等价于 sizeof(int)) cout << sizeof(arr) << endl; // 输出 5 * 8 = 40
二、sizeof
在数组中的应用
1. 静态数组的大小计算
cpp
复制
int arr[10]; cout << sizeof(arr) << endl; // 输出 10 * 4 = 40(总字节数) cout << sizeof(arr) / sizeof(int) << endl; // 输出 10(数组元素个数)
2. 陷阱:数组作为函数参数传递
当数组传递给函数时,会退化为指针,sizeof
无法正确计算数组大小:
cpp
复制
void func(int arr[]) { cout << sizeof(arr) << endl; // 输出指针大小(如 8,而非数组大小) } int main() { int arr[5]; func(arr); return 0; }
3. 多维数组
cpp
复制
int matrix[3][4]; cout << sizeof(matrix) << endl; // 3 * 4 * 4 = 48 cout << sizeof(matrix[0]) / sizeof(int) << endl; // 输出 4(第二维长度)
三、sizeof
与指针的陷阱
1. 指针与数组的区别
cpp
复制
int arr[5]; int* p = arr; cout << sizeof(arr) << endl; // 输出 20(5 * 4) cout << sizeof(p) << endl; // 输出 8(指针变量的大小,与指向内容无关)
2. 动态分配的内存
sizeof
无法计算动态分配内存的大小:
cpp
复制
int* dynamicArr = new int[100]; cout << sizeof(dynamicArr) << endl; // 输出 8(指针大小,而非数组大小)
四、sizeof
在结构体和类中的应用
1. 内存对齐的影响
结构体/类的大小可能因内存对齐规则而大于成员大小的总和:
cpp
复制
struct Example { char c; // 1 字节(对齐到 4 字节边界) int i; // 4 字节 }; cout << sizeof(Example) << endl; // 输出 8(1 + 3填充 + 4)
2. 空类和虚函数
cpp
复制
class Empty {}; cout << sizeof(Empty) << endl; // 输出 1(空类占位) class Base { virtual void func() {} }; cout << sizeof(Base) << endl; // 输出 8(虚表指针大小,64位系统)
五、sizeof
的高级用法
1. 与 decltype
结合
cpp
复制
int x = 10; cout << sizeof(decltype(x)) << endl; // 输出 4(等价于 sizeof(int))
2. 编译时计算
sizeof
在编译时求值,可用于模板元编程:
cpp
复制
template <typename T, size_t N> void printSize(T (&arr)[N]) { cout << "数组大小:" << N << endl; } int arr[5]; printSize(arr); // 输出 "数组大小:5"
六、sizeof
与 strlen
的区别
场景 | sizeof | strlen |
---|---|---|
字符数组 char str[] | 计算总字节数(包括 \0 ) | 计算字符串长度(直到 \0 ) |
动态字符串指针 | 返回指针大小(如 8) | 需要有效 \0 结尾,否则未定义行为 |
示例:
cpp
复制
char str[] = "Hello"; cout << sizeof(str) << endl; // 输出 6('H','e','l','l','o','\0') cout << strlen(str) << endl; // 输出 5
七、总结:sizeof
的核心规则
-
编译时求值:结果在编译阶段确定,不执行表达式。
-
类型依赖:计算的是类型或对象的内存占用,而非逻辑内容。
-
数组退化:数组作为函数参数时会退化为指针,
sizeof
失效。 -
内存对齐:结构体/类的大小受内存对齐规则影响。
-
替代方案:动态数组建议使用
std::vector
或std::array
。
示例代码
cpp
复制
#include <iostream> using namespace std; int main() { // 静态数组 int arr[5] = {1, 2, 3, 4, 5}; cout << "数组总字节数:" << sizeof(arr) << endl; // 输出 20 cout << "数组元素个数:" << sizeof(arr)/sizeof(int) << endl; // 输出 5 // 指针陷阱 int* p = arr; cout << "指针大小:" << sizeof(p) << endl; // 输出 8(64位系统) // 结构体内存对齐 struct Data { char c; int i; }; cout << "结构体大小:" << sizeof(Data) << endl; // 输出 8 return 0; }
合理使用 sizeof
可以避免内存错误,但需时刻注意其限制和陷阱!