c++sizeof求类大小 sizeof与strlen对比

  • Post author:
  • Post category:其他




1.空类

空类的大小为1个字节,参看下面实例

class A {};

int main(int argc, char const *argv[])
{
    A a;
    cout<<"A sizeof is: "<<sizeof(a)<<endl;
    return 0;
}

代码输出结果为

A sizeof is: 1

为什么空类大小不为0?主要是为了确保两个不同对象地址不同,必须如此。

类的实例化是在内存中分配一块地址,每个实例在内存中都有一块不同地址。空类也会被实例化,所以编译器会给空类悄悄分配一字节,这样空类实例化以后就有了自己的地址。所以,空类的sizeof结果不能为0而是1。



2.包含虚函数的类

class B {
    public:
        virtual void func() {}
        virtual void func2() {}
        void func3() {}
        static int n;
        int m;
        int *p;
};

int main(int argc, char const *argv[])
{
    B b;
    cout<<"B sizeof is: "<<sizeof(B)<<endl;
    return 0;
}

上面代码输出为:

B sizeof is: 24

我们分析一下这个24结果是如何得到的:

1.在类中,虚函数本身不占用类对象存储空间。

2.非静态函数,静态函数,都不占用类对象存储空间。

3.静态成员变量不占用类对象存储空间。

4.如果有虚函数,不管虚函数有多少个,只有一个虚指针vptr。

在类B中:

func, func2两虚函数,占用8个字节(64位系统)

func3不占用类空间

n是静态成员变量,也不占用类空间。

指针p占用8个字节

m是整形,本身4个字节。因为要进行内存对齐,所有需要8个字节。

因此,最终占用内存为:8+8+8=24。



3.派生类的大小

class C : public B {
    int nn;
    char cc;
    virtual void fn() {}

};

int main(int argc, char const *argv[])
{
    cout<<"C sizeof is: "<<sizeof(C)<<endl;
    return 0;
}

类C继承上面的类B,最后代码运行的结果为

C sizeof is: 32

我们分析一下32怎么来的:

1.普通继承,派生类继承了所有基类的函数与成员,并且按照字节对齐来计算类的大小。

2.虚函数继承,不管如何继承,都继承了基类的vptr。

B类大小是24,C类中虚函数fn继承虚类的vptr,不占用额外空间。int nn占用4个字节,char cc占用1个字节,内存对齐以后,nn与cc占用总共8字节,所以C类总大小为24+8=32。



4.sizeof与strlen区别

sizeof与strlen都是我们平时常用的。注意这两是有很大区别的:

1.首先sizeof是c/c++中的一个单目运算符,而strlen是一个库函数。

2.sizeof计算的是数据类型占据的空间大小,而strlen只是计算字符串的长度。

我们通过一个例子,来具体分析这两者的区别。

#include<iostream>
#include<cstdlib>
using namespace std;

void sizeof_strlen() {
    const char *p = "abcdef";
    char d[] = "abcdef";
    char e[] = {'a', 'b', 'c', 'd', 'e', 'f'};
    char f[] =  {'a', 'b', 'c', 'd', 'e', 'f', 'g', '\0', 'h'};
    printf("%zu %zu\n",sizeof(p),strlen(p));
    printf("%zu %zu\n",sizeof(d),strlen(d));
    printf("%zu %zu\n",sizeof(e),strlen(e));
    printf("%zu %zu\n",sizeof(f),strlen(f));


    int nums[] = {1, 2, 3};
    printf("%zu\n", sizeof(nums));
    printf("%zu\n", strlen(nums));
}

上述代码,大家先稍微思考两分钟,输出结果应该分别是多少??

首先对于char *p,指向的是一个字符串,注意实际存储的是一个字符数组,并且会自动添加’\0’表示字符数组结束。sizeof计算的是指针p本身的长度,因为机器是64位系统,所以sizeof§为8,而strlen§为字符数组的长度(注意需要刨掉’\0’)为6。

对于char d[],同样会将字符串展开为字符数组,并且会自动添加’\0’表示字符数组结束。char为1字节,字符串本身有6个字符,加上添加的’\0’,因此sizeof(d)为7, strlen(d)为6。

char e[]本身就是字符数组,包含6个字符,此时sizeof(e)为6。而strlen(e)求的是字符串长度,默认的是以’\0‘结束。此时找不到’\0’,会输出一个不确定值,比如作者运行的时候输出就为12。

char f[]与char e[]的不同在于,里面有’\0’字符。所以,sizeof(f)为9,而strlen(f)则是’\0’字符前的长度为7。

nums是整形数组,一个整数占4字节,nums有三个元素,sizeof(nums)为12。

而strlen求的是字符串的长度,nums为整形数组,所以strlen(nums)会报错,编译不通过。



版权声明:本文为bitcarmanlee原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。