【总结】C++与C#中的struct结构体
C++结构体
支持继承,甚至可以多继承,虚继承,多态,重载运算符,模板,定义友元函数,友元类等。
C++ 结构体和类区别
- 和C不一样,C++结构体可以有成员函数、构造函数、继承和多态,相比C增加了很多功能
- 默认public,无论是继承还是修饰变量(本质区别),这点和class,C#都不同
struct B : A。继承默认是public的,而class默认是private的
- struct可以继承class,同样class也可以继承struct,那么默认的继承访问权限是看子类到底是用的struct还是class
你可以将程序里所有的class全部替换成struct,它依旧可以很正常的运行
- 关键字“struct”不能用于定义模板参数,而class可以
- 结构体没有默认构造函数,所以没有定义构造函数时可以使用 ={ } 初始化列表赋值public变量
- 思想: struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。
结构体对象所占的空间大小
字节对齐:每个成员前面的字节数(即成员地址)需要是自身大小的倍数 。即当前成员的偏移量(起始位置)必须是成员变量大小的整数倍,不是的话在后面填充字节。
字节对齐的目的是让计算机快速读写,是一个以空间换取时间的方式。
内存补齐:结构体大小必须是最大成员的倍数。不是的话还要填充。
- 32位机中,如果成员大于4字节则以4字节整数倍为基准对齐;64位机中则以8字节作为基数上限。
- 补齐是为了让这个结构体定义的数组变量时候,数组内部,也同样满足内存对齐的要求。
#pragma pack(n) 表示默认以n字节对齐(上限),若某变量(如int)的字节大于n,则以n的倍数对齐,内存补齐同理
例题1:
sizeof (64位机)
struct
st_t {
int
status;
short
*pdata;
char
errstr[32];
};
注意64位机指针占8个字节,而且要补齐4个字节,所以4+8+32+4=48
例题2:
64位机上,一个结构体有三个成员,分别是char、int、short类型,三个成员位于结构体中不同位置时整个结构体的大小可能是哪些值?
三个数据,一共6种排列:
int
4B
char
1B
short
2B
根据内存对齐原则:
1.
char
int
short
char1 + 空3 + int4 + short2 + 空2 = 12
2.
char
short
int
char1 + 空1 + short2 + int4 = 8
3.
int
short
char
int4 + short2 + char1 + 空1 = 8
4.
int
char
short
int4 + char1 + 空1 + short2 = 8
5.
short
int
char
short2 + 空2 + int4 + char1 + 空3 = 12
6.
short
char
int
short2 + char1 + 空1 + int4 = 8
C#结构体
与C++结构体区别
默认访问权限为 private
struct是值类型,其实例在栈上分配内存
class是引用类型,其实例在堆上分配内存
比如 int 是结构体int32的关键字,所以是值类型。 是从System.ValueType继承的,但是只有他们装箱(boxing)的引用类型是从这里继承的,他们的值类型不是从任何地方继承的,就是.net的内部类型。
System.ValueType是从System.Object继承的。你用了struct关键字,就表明了System.ValueType的继承关系,无需指明。
所有结构体都继承ValueType父类,结构体不能被其它类继承。
结构体可以实现接口,却不能继承其他的class
因为值类型不能继承类类型
结构体定义
关于C++中结构体的定义声明,我用一段代码来演示吧。
// 类型别名:为现有类型创建别名 typedef int in; // 这里是定义结构体的同时用typedef取了个叫Stu的别名 typedef struct Student { string name; }Stu; // 还可以用using声明别名 using init = int; in i = 0; // 结构体对象的几种构造方式 Stu s1{ "xx" }; Student s2{ "ss" }; // 在C语言中你不能使用这种构造方式。。 struct Student s3(); // 在C语言中,Stu视为struct Student init j = 0; // decltype可以获得对象或函数返回值的类型,从而进行一些操作。但是这不是反射,这是编译时获取的类型 decltype(s1) type = s2;
以上代码表明了C++和C中定义结构体变量的区别
C语言通常用typedef或struct Student的方式定义
C++中你可以用using别名,Student直接定义
C#中,和类差不多
共用体
定义:union name { };
共用体的作用就是不同的类型的变量共享同一个地址,好处是节省开销,缺点是同一时刻仅仅能存储一个成员。
共用体的大小是所有成员中占内存最大的那个,初始化时只能有一个常量。
- 共用体不能同时引用几个成员,他只能用上一次赋值过的那个成员,其他成员都被覆盖掉了
- 共用体变量不能初始化
- 共用体变量不能作为函数参数(指针可以)
- 大小端模式(这个有兴趣可以了解)
例题:
下列代码的输出结果有可能是哪些
#include<stdint.h>
#include<stdio.h>
union X
{
int32_t a;
struct
{
int16_t b;
int16_t c;
};
};
int main(){
X x;
x.a=0x20150810;
printf("%x,%x\n",x.b,x.c);
return 0;
}
答:2015,810 或 810,2015
0x20150810 如果按照大端模式存储(和阅读习惯一致):从低地址到高地址:20 15 08 10
输出从低地址到高地址:20 15 08 10
如果按照小端模式存储:从低地址到高地址:10 08 15 20
输出从高地址到低地址:08 10 20 15