一、C语言中的struct

在C语言中,struct是一种自定义数据类型,所以在C语言中,struct不能包含任何函数,否则编译器会报错。因为C语言是面向过程的编程。采用过程性编程首先考虑要遵循的步骤,然后考虑如何表示这些数据。也就是先考虑过程后考虑数据,这样方法和数据就分开了。而在C语言中结构体就是为了考虑数据的封装而存在的。
还有就是在C语言中不能存在空结构体,否则编译器会报错。原因很简单,C语言中结构体就是为了封装数据类型,统一为一个新的struct数据类型,既然是封装数据而存在,那么定义一个结构体不给任何数据,那还封装个什么。
所以总结就是:
(1)C语言中的结构体只是封装数据用的,不能包含任何函数。
(2)C语言中的结构体不能为空结构体。

二、C++中的struct

首先C++是面向对象的编程。首先考虑数据,同时还要考虑如何使用数据。对待一种事物,首先用一个对象表示这个事物 的方方面面,包括对象的属性,和对对象的属性(数据)的操作。即首先从用户的角度考虑对象,描述对象所需要的数据,以及描述用户与数据交互所需要的操作。完成对接口的描述后,需要确定如何实现接口和数据的存储,最后使用新的设计方案创建出程序。这里可以说就是面向对象的原则之一:“依赖倒转原则”。依赖接口编程序。
在C++中struct与class没有什么特别的区别。唯有畅谈的一个区别,就是struct里的数据成员默认都是public类型的,而class里面的数据类型默认是private类型的。为什么会这样呢?主要还是为了兼容C语言程序中的结构体,C语言程序中的结构体就是随便访问数据的。C++里在兼容C语言程序中的struct的同时,尽量将struct和class的其他属性设置成一致。所以C++中的struct除了默认属性是public之外,其他和class的使用没有区别,包括构造函数,析构函数,可以有空类,也允许有空结构体。
所以总结就是:
(1)C++中的结构体默认属性是public属性。
(2)C++中的结构体出去第一点之外,其他的使用和class一样。包括有默认构造函数,默认析构函数,可以自定义构造函数,可以有其他成员函数,也可以像class一样为一个空体。

另外在C语言里结构体内的变量不可以初始化,因为在用结构体定义变量之前,没有给struct分配栈空间(在网上搜了好多,都是这样说的),换句话说C语言里struct只是一个自定义变量类型,怎么可能直接给变量类型里面的东西赋值呢?比如int也是一个变量类型,怎么可能把int里面的东西赋值呢,所以struct也是这个意思。只有用struct定义出来变量的时候,给定义出来的变量赋值。
注意,这个时候就更不能将C++的结构体和C语言的结构体相提并论,因为C语言结构体只是一个单纯的自定义数据类型,但是在这里struct已经超脱普通自定义类型概念了,因为这里struct里面可以用成员函数,是封装数据和方法的类型,是一个包含代码实现设计的封装。
但是C++的结构体和类却可以初始化,按道理说,类和结构体我们都说没有实例化,没有分配栈空间。创建对象才是实例化,分配栈空间,构建对象,这个时候才有真正意义。这样想的话,感觉C++里面的类和结构体也不可以给成员变量初始化。但是事实是可以初始化的。
如下变量初始化代码及运行情况:

class A
{public:int m_val = 10;int m_tmp = 20;
};struct B
{int s_a = 90;int s_b = 100;
};int main()
{A a;A b;cout << a.m_val<< endl;cout << b.m_tmp <<endl;B c;B d;cout << c.s_a << endl;cout << d.s_b << endl;return 0;
}


如果我们不初始化直接输出呢?我没有敲代码看结果之前,我觉得要么就是随机值,要么就是0。我在博客上还搜了一下,发现有一篇**2015年博客**说在C++里结构体里面变量不初始化的话,创建对象输出变量值是0,类创建对象,输出成员变量值是随机值。于是我敲了几行代码自己看一下结果,发现并非如此。代码及输出结果如下:

class A
{public:int m_val;int m_tmp;
};struct B
{int s_a;int s_b;
};int main()
{A a;A b;cout << a.m_val<< endl;cout << b.m_tmp <<endl;B c;B d;cout << c.s_a << endl;cout << d.s_b << endl;return 0;
}

运行结果:

直接报错!既不是0也不是随机值。更不是结构体里面变量是0,类里面成员变量是随机值。这个基本可以确定是跟编译器有关。因为我看的那篇博客里面有代码和运行结果,而且是2015年博客,编译器肯定更加完善,发现有明显不合适的使用时,直接报错。
我觉得这些问题可以自己思考动手实践看结果。可以引发兴趣,在网上查资料思考。但是一直纠结深究觉得没必要,一般情况下,在C++里我们只把类(struct)看成对数据和方法封装的东西。里面包括一些设计和实现。创建对象的时候,类才算配的上用场,所以即使现在编译器允许初始化,我们也一般情况下不初始化。创建对象的时候,再对对象的数据成员进行初始化赋值等操作。(如果类里面有常变量或者其他必须定义的时候就初始化的变量,我们才给一个初始值)。

三、C++中空结构体和类大小

直接用程序计算看一下:

struct A
{};class B
{};
int main()
{A a;cout << sizeof(a) << endl;B b;cout << sizeof(b) << endl;return 0;
}

运行结果:

空类和空对象的大小都是1(由于这里结构体和类一样,就单独讨论类)。
这是因为C++中标准规定,任何不同的对象不能拥有相同的内存地址。如果空类大小为0,文声明这个类的对象数组,那么数组中每个对象内存都是0,导致数组中的它们都拥有了相同的地址,这样违背了C++标准。
所以,不只是类,其他任何类型,都不允许大小为0。所以编译器为每个空类空结构体都增加了一个虚设的字节(书上得知有的编译器可能不止增加一个虚设字节)。这样就可以保证空对象和空结构体的大小不会是0,保证了它们的对象拥有彼此独立的空间。
还有之前听到老师说的另一种解释说是因为空类里面有默认构造函数和析构函数,所以大小为1字节,但是我理解不了,查完资料之后我更相信上面C++标准规定的说法,对老师的这一个观点存质疑态度。

在这里提出对象必须拥有彼此独立的空间,就想到了共用体。共用体是一种数据格式,能够存储不同的数据类型,但只能同时存储其中一种数据类型。就想着共用体里有两个对象会怎么样,这个时候是两个对象用同一个空间?这样就违背了前面说的编译器要求对象必须有独立的空间,用共用体定义一个变量的时候,里面的对象会调用构造函数吗?如果都调用构造函数的话,那就是两个对象用一个空间了,如果为了避免两个对象用一个空间而只选择一个对象构造的话,那么会选择哪一个对象构造呢?
突然想起很多,打开VS敲了一下代码,一开始想要看一下共用体里面的两个对象的构造和析构情况,我们使用共用体里面的对象的时候至少同时存在一个对象,所以至少会有一个对象调用构造函数,那么如果先构造的对象还没析构就构造了另一个对象的话,那么就产生了两个对象同时存在一个空间,就违背了上面的理论。所以理想情况下,应该是一个对象使用这个空间,另一个对象使用前,前一个对象一定会调用析构函数销毁,另一个对象才会调用构造函数,这样就完美岔开了,就不会说两个对象同时存在一个空间中。为了清楚的看到构造析构的过程和顺序写出如下代码:

class A
{A() {cout << "一个对象构造" << endl;}~A() {cout << "一个对象销毁" << endl;}
public:int m_val;
};
int main()
{union UU{A a;A b;};UU t;return 0;
}

写到UU t;这句代码的时候就报错了,说“无法引用共用体的默认构造函数——它是已删除的函数”。看起来是因为构造函数被我们重写造成的。但是当我把构造函数删除,只留下一个析构函数的时候,还是会报这样的错误。当把构造函数和析构函数都删除才没有报错。如下代码:

class A
{public:int m_val;
};
int main()
{union UU{A a;A b;};UU t;t.a.m_val = 10;t.b.m_val = 20;cout << t.a.m_val << endl;cout << t.b.m_val << endl;return 0;
}

运行结果:

因为我们不能写构造函数和析构函数,所以最后也没得出什么结果。但是由于共用体要求里面的数据类型要求某一时刻只能有一个成员是当前成员。所以应该是a和b是不同时存在的,用共用体切换使用它们俩的时候,应该一直不断的伴随着对象的构造和析构,只不过我们没办法重写构造函数和析构函数在里面添加输出语句来观察构造和析构过程。

struct和class之间问题(+引发的个人思考,和对共用体思考)相关推荐

  1. golang 学习(二十四)结构体struct 和 json之间的转换

    结构体struct 和 json之间的转换 import ("encoding/json""fmt""math/rand""tes ...

  2. 【零基础学C语言】知识总结八:struct 结构体与 union 共用体

    struct 结构体 struct即结构体,C程序中经常需要用相关的不同类型的数据来描述一个数据对象.例如,描述学生的综合信息时,需要使用学生的学号.姓名.性别等不同类型的数据时,像这种数据类型总是在 ...

  3. 由两个问题引发的对GaussDB(DWS)负载均衡的思考

    摘要:GaussDB(DWS)的负载均衡通过LVS+keepAlived实现.对于这种方式,需要思考的问题是,CN的返回结果是否会经过LVS,然后再返回给前端应用?如果经过LVS,那么,LVS会不会成 ...

  4. 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程...

    简述C#中IO的应用 在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.IO ...

  5. 推易吧重生,引发我们对币圈项目的集体思考

    区块链这个行业自2016年以来飞速发展,经历过2018.2019.2020近三年漫长熊市,留下过掠影的项目方不计其数.其中有不少因为被砸盘而破产的项目,在大多数人的认知里,遭遇砸盘的项目基本就凉凉了. ...

  6. 一张工资条引发的关于国内OA协同办公产品的思考

    年前公司财务回家生娃,年后回来这算工资发工资的人就空缺了.刚开始创业的时候,媳妇帮着发,后来公司稳定了有了财务,如今这谁都指望不上,好吧,撸起袖子自己上吧.于是,我便经历了创业8年来的第一次算工资,真 ...

  7. 傅里叶分析中的时频域之间的关系(以及一点对于DFT的一点思考)

    目录 序言 连续傅里叶级数(FS) 连续傅里叶变换(FT) 离散傅里叶级数(DFS) 离散时间傅里叶变换(DTFT) 总结 对于DFT的一点认识(思考) 序言 这里的傅里叶分析指的是: 连续情况下的: ...

  8. C语言学习笔记11-结构体(struct、结构作为函数参数、结构数组)、联合体/共用体typedef; union(大、小端序)

    C语言-结构类型 程序中的数据都需要有类型支撑,当数据很复杂时(不是简单的一个值,如时间信息:年月日时分秒6个数据需要作为一个整体),我们需要声明一个新的结构类型来描述这种复合的数据(可以包含很多不同 ...

  9. 【了解结构体与指针、数组、函数、字符串之间的关系】(学习笔记14--结构体)

    目录

最新文章

  1. 多线程利器-队列(queue)
  2. 当 HTTP 连接池遇上 KeepAlive 时
  3. linux多线程信号总结
  4. 仿哔哩哔哩出错404错误页面源码
  5. HetGNN-Heterogeneous Graph Neural Network 异构图神经网络 KDD2019
  6. Mysql 电商常用的时间操作(当天,昨天,7天,30天,半年,全年,季度等等)...
  7. ROS安装时rosdep init与rosdep update问题解决方法(2022.04.08亲测)
  8. [YARN-1963] 支持同一个队列内作业按优先级调度
  9. java抽奖代码_纯java代码实现抽奖系统
  10. Hexo 添加百度统计
  11. iOS 去除字符串中的H5标签
  12. Android中浏览PDF文件
  13. Ubuntu开机一直卡在[OK] Started GNOME Display Manager处,解决方案!
  14. cs服务器(cs索沛服务器)
  15. 【计算机组成原理】使用VHDL语言设计一个二输入异或门
  16. lsnrctl command not found
  17. 大数据是不是互联网思维?
  18. eclipse总是运行之前的代码,控制台只显示原先的结果
  19. python_爬虫_七麦网
  20. 杜教筛 狄利克雷卷积入门

热门文章

  1. 操作系统实验报告13:线程池简单实现
  2. [图像处理] Python+OpenCV实现车牌区域识别及Sobel算子
  3. 【数据结构与算法】之链表的操作和使用
  4. LeetCode Algorithm 572. 另一棵树的子树
  5. Java IO流 、 Properties 、 枚举
  6. 【Linux】一步一步学Linux——ps命令(119)
  7. 【Qt5.8】Qt5.8中串口类QSerialPort
  8. [Qt教程] 第18篇 2D绘图(八)双缓冲绘图
  9. 二维数组 赋值_3.9数组(数组基本使用、数组的循环、数组拷贝、数组排序、多维数组)...
  10. 每天一道LeetCode-----给定二维数组代表海域和岛屿,计算有多少个孤岛