c++ sizeof对象大小整理

1. sizeof 是运算符,而不是函数。

2. 当sizeof 的对象是表达式时,求的大小是表达式返回值的类型大小,但并不计算表达式的值,比如:

1 char c = 1;
2 int i = 2;
3 cout << sizeof(c + i) << endl;
4 cout << sizeof(c = c + i) << endl;

前者c + i会隐式类型转化为int类型(类型提升),因此返回4(32位系统), 而后者虽然运算时也是转化为int,但赋值给c时又会转化为char,因此返回的是1。

3. 如果对象是函数,则返回函数返回值类型大小,如:

 1 long long foo()
 2 {
 3     cout << "foo() has been called" << endl;
 4     return 0;
 5 }
 6 
 7 int main(int argc, char **argv)
 8 {
 9     cout << sizeof(foo()) << endl;
10     return 0;
11 }

执行后输出8, 不会输出 foo() has been called.说明函数没有真正执行,而只是判断了下返回类型。

4. 当sizeof的对象是数组时,返回数组总大小,而当对象是指针时,返回指针本身的大小,而不是指示内存空间的大小。因为指针本身就是一个无符号整型数, 因此int *p ,sizeof(p)返回的大小是sizeof(void *), 32 位系统返回4,即32位。但注意当数组名作为实参传入函数时,会自动转化为指针类型,如下:

 1 void foo(int a[])
 2 {
 3     cout << sizeof(a) << endl; /* 4 */
 4 }
 5 int main(int argc, char **argv)
 6 {
 7     int a[] = {1, 2, 3, 4};
 8     int *p = a;
 9     cout << sizeof(a) << endl; /* 16 */
10     cout << sizeof(p) << endl; /* 4 */
11     foo(a);
12     return 0;
13 }

5. sizeof 无法获取动态分配的内存大小,即使用malloc动态的分配内存,无法使用sizeof获取其大小。

6. 注意c_style字符串末尾有一个\0结束符,也需要占一个char空间,因此sizeof("1") 返回2。而strlen返回的是字符数,不包括\0结束符。

7. 理论上一个结构体所占空间是所有成员的大小总和,但由于考虑到对齐问题,会有填充字节。

struct node1
{
    int a;
    int b;
    char c;
    char d;
};

struct node2
{
    int a;
    char b;
    int c;
    char d;
};

node1大小为12字节, node2大小为16字节。

结构体后面的动态数组,即不指定大小的数组,sizeof 时不包括动态数组的大小,即

1 struct node
2 {
3     int a;
4     char c;
5     int d[];
6 };

返回依然是8。

8. 类的大小:

 (1). 空类的大小。空类型实例中不包含任何信息,应该大小为0. 但是当我们声明该类型的实例的时候,它必须在内存中占有一定的空间,否则无法使用这些实例。至于占用多少内存,由编译器决定。g++中每个空类型的实例占1字节空间。注意空struct即空类,这就是为什么c++的空struct占1个字节的原因。

 (2). 构造函数、析构函数、成员函数调用时只需知道函数地址即可,而这些函数的地址之与类型相关,而与具体的实例无关,因此不会在实例中额外添加任何信息。

 (3). 静态数据成员放在全局数据成员中,它不占类实例大小,多个类实例只有一个实体。可以看作是一种特殊的全局变量。

 (4). 类的非静态数据成员和struct类似,也需要对齐,可能需要字节填充。

 (5). 如果一个类中有虚函数,则该类型会生成一个虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针,因此类大小必须加上一个指针所占的空间。如果是普通继承,子类和基类共享这个指针。

 1 class A
 2 {
 3     public:
 4         static int a;
 5         static char c;
 6         A(){};
 7         ~A(){};
 8         void foo(){};
 9 }; 
10 // 类A的大小为1字节,等于空类大小,静态数据成员a、c和成员函数都不占类的大小。
11 
12 class B
13 {
14     public:
15         int a;
16         char c;
17         A(){};
18         ~A(){};
19         void foo(){};
20 };
21 // 类B的大小为8字节
22 
23 class C
24 {
25     public:
26         int a;
27         char c;
28         A(){};
29         ~A(){};
30         void foo(){};
31         void virtual bar(){};
32 };
33 // 类C的大小为12。数据成员8,加上指向虚拟函数表的指针。

 

(感谢http://www.cnblogs.com/zhangyz/articles/4736758.html)

posted on 2017-03-29 16:49  pandawuwyj  阅读(2839)  评论(0编辑  收藏  举报

导航