sizeof

内存中数据对齐

计算机中内存空间中各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是数据对齐。

  • 访问数据的内存地址要满足一定的条件:能被这个数据的长度所整除。 例如,1字节数据已经是对齐的,2字节的数据的地址要被2整除,4字节的数据地址要被4整除。
  • 数据对齐并不是操作系统的内存结构的一部分,而是C P U结构的一部分。当C P U访问正确对齐的数据时,它的运行效率最高。
  • 字节对齐是在编译时决定的,一旦决定则不会改变,因此即使有对齐的因素,也不会出现一个结构在运行时尺寸发生变化。

sizeof 和strlen 的区别

  • sizeof是关键字,strlen是函数。
    cout << strlen("\0") << endl; //0
    cout << sizeof('\0') << endl; //1,被当作字符来处理
    cout << sizeof("\0") << endl; //2,被当作字符串来处理,默认添加'\0'作为结尾

    char str[] = "0123456789";
    cout << strlen(str) << endl;  //10
    cout << sizeof(str) << endl;  //11

strlen执行的计数器的工作,它从内存的某个位置开始扫描,直到碰到第一个字符串结束符’\0’为止,然后返回计数器值。
sizeof是关键字,它以字节的形式给出了其操作数的存储大小,操作数可以是一个表达式或类型名,操作数的存储大小由操作数的类型决定。

  • sizeof类型(自定义类型)、函数作为参数,strlen只char*作为参数,而且必须是以‘\0’结尾。
    sizeof以函数作为参数,例如int g(),则sizeof(g())的值等价于sizeof(int)的值。
  • sizeof后如果是类型需要加括号,如果是变量则不需要加括号,这是因为sizeof是操作符而不是函数。
int a;
cout << sizeof a << endl;  //无需加括号,正确
cout << sizeof (int) << endl; //需要加括号
  • 大部分编译程序的sizeof都是在编译的时候计算,而strlen在运行期间计算。
char ch[6];
int num[sizeof(ch)];  //真确
int num1[strlen(ch)]; //错误

sizeof 基本数据类型

819930-20190605115554714-1815181463.png

sizeof 结构体

结构体的sizeof是所有成员对齐后长度相加,而union共用体的sizeof是取最大的成员长度。
结构体按照最大成员长度对齐,占用内存是即最大成员的整数倍。

struct A1 {
    int a;
    char c;
    A1();
    ~A1(){}
};

struct A2 {
    double d;
    float f;
    int a;
    char c;
    A2();
    ~A2() {}
};

int main(int argc, char* argv[]) {
    cout << sizeof(A1) << endl;  //8
    cout << sizeof(A2) << endl;  //24
    return 0;
}

sizeof 只计算栈中分配的大小

struct A1 {
    int a;
    char c;
    static float c1;   //BSS段,不属于栈区
    A1();
    ~A1(){}
};

struct A2 {
    int a;
    char c;
    float c1;
    A2();
    ~A2(){}
};

int main(int argc, char* argv[]) {
    cout << sizeof(A1) << endl;   //8
    cout << sizeof(A2) << endl;   //12
    return 0;
}

sizeof 指针和引用

指针进行sizeof操作得到的是指针本身(所指向的变量(对象)的地址)的大小。

struct A {
    int a;
    char c;
};

int main(int argc, char* argv[]) {
    A a;
    A &b = a;
    cout << sizeof(b) << endl;  //8
    A *c = &a;
    cout << sizeof(c) << endl;  //4

    return 0;
}

数组作为参数传递给函数时传的是指针而非数组,传递的是数组的首地址。

int g(char ch[])
{
    return sizeof(ch);
}

int _tmain(int argc, _TCHAR* argv[])
{
    char ch[6];

    cout << sizeof(ch) << endl; // 6
    cout << g(ch) << endl; //4
    return 0;
}

sizeof 与 类

sizeof 之虚函数

虚函数是由虚函数表和虚表指针来动态绑定的,在计算sizeof时,无论有多少个虚函数,其只计算sizeof(虚表指针)=4(64位为8)。

class A1 {
    int a;
    char c;
    static char c1;   //BSS段,不属于栈区
    A1();
    ~A1() {}
    virtual void f1() {}
    virtual void f2() {}
    virtual void f3() {}
};

int main(int argc, char* argv[]) 
{
    cout << sizeof(A1) << endl;  //12
    
    return 0;
}

sizeof 之继承

  • 基类的sizeof结果只与基类有关。
  • 因存在继承关系,所以派生类的sizeof结果需要加上基类的sizeof结果。
  • 当基类和派生类均有虚函数时,只计算一次sizeof(虚表指针)。
class A1 {
    int a;
    char c;
    static char c1;   //BSS段,不属于栈区
    A1();
    ~A1() {}
    virtual void f1() {}
    virtual void f2() {}
    virtual void f3() {}
};

class A2 : public A1{
    float f;
    void f1(){}
    void f2(){}
    void f3(){}
    virtual void g1(){}
    virtual void g2(){}
};

int main(int argc, char* argv[]) 
{
    cout << sizeof(A1) << endl;  //12,class A1占用12Byte
    cout << sizeof(A2) << endl;  //16,需要加上class A1占用12Byte
    getchar();
    return 0;
}

sizeof 之空类

class A1 {

};

class A2 : public A1{

};

int main(int argc, char* argv[]) 
{
    cout << sizeof(A1) << endl;  //1
    cout << sizeof(A2) << endl;  //1

    return 0;
}

sizeof 之成员函数

一个类中,虚函数本身、成员函数(包括静态与非静态)都是不占用类对象的存储空间的。

class A1 {
    void f1();
    virtual int f2();
    static int f3();
};



int main(int argc, char* argv[]) 
{
    cout << sizeof(A1) << endl;  //4
    return 0;
}

sizeof 之对象

class A1 {
public:
    void f1();
    static int f3();

private :
    int a;
    static int b;
    char c;
};

int main(int argc, char* argv[]) 
{
    A1 a1;
    cout << sizeof(a1) << endl;  //8
    return 0;
}

sizeof 之虚继承

虚承继的情况:需要增加一个虚表指针,因而增加4byte

class A {
public:
    int a;
};

class B : virtual public A 
{
public:
    int b;
};

class C : virtual public B {
};

int main() 
{
    cout << sizeof(A) << endl;  //4
    cout << sizeof(B) << endl;  //12
    cout << sizeof(C) << endl;  //16

    return 0;
}

sizeof 之多重继承

class A {
public:
    int a;
};

class B : virtual public A {
};

class C : virtual public A {
};

class D : public B, public C{
};


int main() 
{
    cout << sizeof(A) << endl;  //4
    cout << sizeof(B) << endl;  //8
    cout << sizeof(C) << endl;  //8
    //这里需要注意要减去4,因为B和C同时继承A,只需要保存一个A的副本就好了,sizeof(D)=4(A的副本)+4(B的虚表)+4(C的虚表)=12  
    cout << sizeof(D) << endl;  //12
    return 0;
}

sizeof 虚继承虚函数

class A
{
public:
    virtual void aa() { }
    virtual void aa2() { }
private:
    char ch[3];
}; 

class B : virtual public A
{

}; 

class C : virtual public A
{
public:
    virtual void bb() {  }
    virtual void bb2() {  }
};

int main(void)
{
    cout << sizeof(A) << endl; // 8
    cout << sizeof(B) << endl; // 12
    cout << sizeof(C) << endl; // 16
    return 0;
}

转载于:https://www.cnblogs.com/chay/p/10978250.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值