sizeof operator

sizeof 是编译期运算符,不会执行任何实质的计算,例如:

#include <iostream>
 
using namespace std;
int main() {
    int y;
    int x = 11;
    y = sizeof(x++); //value of x doesn't change
    cout<<y<<" "<<x;// prints 4 11
}

sizeof(x) returns the amount of memory (in bytes) that the variable or type x occupies. It has nothing to do with the value of the variable.

int a[10];
assert(&(a[0]) + sizeof(int) == &(a[1]));
 
T t;  // varialbe t has type T
assert(sizeof(t) == sizeof(T)); // sizeof只和类型相关
 
sizeof(std::vector<int32_t>);  // =24 on my machine
std::vector<int32_t> a;
assert(sizeof(a) == sizeof(std::vector<int32_t>));
a.reserve(5);
sizeof(a); // =24
a.resize(10);
sizeof(a); // =24
 
int32_t b[10] {};
sizeof(b); // =40
sizeof(b[0]); // =4
 
template<typename T>
void PrintSize(T t)
{
    printf("obj %s has size %lu\n", typeid(t).name(), sizeof(t));
}
 
PrintSize(b);  // print 8, 传参时b退化为int32_t*
 
struct Foo {
    int a;
    char b;
};
 
sizeof(Foo); // =8, 内存对齐

see https://godbolt.org/z/no8KW1dY5

一些规则

sizeof一个空类,结果通常为1. 理论上来说,空类应该不占用空间,但对象必须有唯一的地址,如果不占空间,那就可能发生多个实例的地址相同的情况。因此,标准规定,空类的size为1. 当然,各编译器有实现的自由。

sizeof一个class和sizeof它的实例化对象,必然相等。因为sizeof是编译期运算符,它的结果和变量的值毫无关系。

sizeof一个带虚函数的类,成员隐性的增加了一个指向vtable的指针,因此会在原有基础上加上该指针的大小。sizeof和成员函数的数量,以及虚成员函数的数量无关1。所有对象共享一份vtable,但每个对象内部都包含一个指向vtable的指针。

sizeof一个带静态数据成员的类,静态数据不参与计算size,因为静态变量不存在对象的空间中,静态变量存在静态内存区。所有实例共享的是同一份静态数据。

live demo: https://godbolt.org/z/Wc59Psb6E

更多规则请参考ref1.

Reference

  1. C++ sizeof 总结

Footnotes

  1. 简单来说就是成员函数(虚或非虚)都是一个类一份,类的所有实例没必要各自copy一份,因为它们对所有成员都是一样的。因此,它们不占用对象的大小,它们存在代码段内存区。更多参考:https://stackoverflow.com/a/9451502