关于结构体的那些事

6 篇文章 0 订阅


之前看八股的时候,简略看了一下结构大小的问题,现记录一下

// 64位系统
#include<iostream>
using namespace std;

struct Test
{
	int a;
	char b;
};

int main(){
	cout<<sizeof(Test)<<endl; // 输出8
	return 0;
}

结构体和类的大小与什么有关

  1. 遵循内存对齐原则
  2. 类的大小只与普通数据成员有关(非静态成员变量)
  3. 虚函数类会增加虚函数表指针的大小
  4. 虚继承类会增加虚基指针的大小
  5. 空类大小为1

内存对齐问题

什么是内存对齐?

计算机系统对基本数据类型在内存中的存放有限制,会要求这些数据的首地址的值是某一个值(有效对齐值)的整倍数,这样便于存取。

为什么要内存对齐?

有了内存对齐和有效对齐值,操作系统就可以一次读出特定的值,而不用进行“拆分”

有效对齐值

尽管字节是最小的内存单位,但是处理器不会按照字节大小来存取内存(毕竟大部分的基本数据类型都是4字节、8字节等),例如,如64位操作系统下的存取单位是8,也叫默认“对齐系数”

#pragma pack(8) // 64位系统

而有效对齐值则是需要用结构体的值与默认对齐系数进行比较

有效对其值:是给定值#pragma pack(n)和结构体中最长数据类型长度中较小的那个。有效对齐值也叫对齐单位。

举个栗子

#include<iostream>
using namespace std;

#pragma pack(8) // 64位系统下

struct Test1
{
    int a[5];  // 4*5 = 20
    int *b; //
};

struct Test2
{
    int a[5];  // 4*5 = 20
    int &b; // 64位是8
};

struct Test3
{
    int a;
    char b;
};


int main()
{
	 cout<<"结构体Test1占用的内存空间字节大小为:"<<sizeof(Test1)<<endl;  // 32
	 cout<<"结构体Test2占用的内存空间字节大小为:"<<sizeof(Test2)<<endl; // 32
     cout<<"结构体Test3占用的内存空间字节大小为:"<<sizeof(Test3)<<endl;// 8
}

好,内存对齐讲完了,大概就是这样.

对于内存对齐,只需要先计算出有效对齐值,再按照声明顺序在内存中排兵布阵就行.

但是,上面有一个很有意思的东西,结构体Test2中有一个int &b,相信有人会疑惑三连问了

这个不是引用吗?
引用不是需要初始化吗?
引用不是只是别名吗?怎么会有大小?

慢慢来解析!

引用的问题

左值右值引用我就不说了,网上有太多博客介绍

首先引用需不需要初始化,在我们之前的观念中,引用是一个对象的别名,如果对象都没有,就别谈别名了

int main() {

    int  a = 10; // 左值 对象
    int &b = a; // 左值引用 对b起别名

    return 0;
}

但是!为什么结构体里可以不用初始化呢?也没有报错?

原因是,结构体Test2里的对象不是定义,而是声明(类也可以,类内声明,内外定义)
而声明则是不会为对象分配空间!所以不会报错

#include <iostream>

extern int& c;

struct Test{
    int a;
    int &b;
};

int main() {
    int  a = 10; // 左值 对象
    int &b = a; // 左值引用 对b起别名
    Test t;  // note: ‘int& Test::b’ should be initialized
 	
 	c = a;  // 声明之后再定义就没错

    return 0;
}

但是实例化之后就会出错!

引用的大小问题

一般我们对引用sizeof()的话,都是计算其指向对象的大小,但是声明没有指向对象,在内存中也会分配空间(如果能合法执行的话)

#include <iostream>
using namespace std;

struct Test{
    int a;
    int &b;
};
int main() {

    int  a = 10; // 左值 对象
    int &b = a; // 左值引用 对b起别名

    cout<<sizeof(a)<<endl; // 4
    cout<<sizeof(b)<<endl; // 4
    cout<<sizeof(Test)<<endl; // 16
}

在结构体里的引用声明大小和指针类型一样!

c++真的是…太神奇了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值