怎么做情侣网站/长沙企业网站设计

怎么做情侣网站,长沙企业网站设计,浙江建设信息港电工证查询,深圳专业做网站专业C初阶——类和对象(二) 本期内容书接上回,继续讨论类和对象相关内容。类和对象属于C初阶部分,主要反映了面向对象编程的三大基本特点之一——封装,在C的学习中占有举足轻重的地位! 一、类对象模型 1.如何…

C++初阶——类和对象(二)

本期内容书接上回,继续讨论类和对象相关内容。类和对象属于C++初阶部分,主要反映了面向对象编程的三大基本特点之一——封装,在C++的学习中占有举足轻重的地位!

一、类对象模型

1.如何计算基于一个类创建出的对象大小?

(1)使用sizeof计算

我们先来复习一下什么是类,什么是对象。类定义了一个新的作用域,类的所有成员都在类的作用域中。通过class关键字将数据与操作(成员函数)绑定。类定义仅仅是逻辑的蓝图,就像是一个房间的设计图纸,并不能真正的住进去,因此,我们需要对类进行实例化才会创建出具体的对象,分配内存空间同一个类可以实例化出多个不同的对象。因此,从实际意义上来说,我们所计算的内存空间,并不是类本身,而是基于类创建出的对象的大小。当然,仅仅从计算这个层面出发,我们可以通过类来计算如果用这个类来创建对象,对象应该会占用多少空间,就好比我们可以通过房屋的设计图纸来计算房屋建成后,理论上会占用多大的面积,我们来举个例子,分别看一看:

  • 第一种计算方法:
    示例1
    在这里,我们先通过类实例化一个对象,就像是先根据图纸把房子建好,然后再测量房子的占地面积。
  • 第二种计算方法:
    示例2
    这里我们并没有示例化一个对象,而是直接计算类的大小,也是很好理解的,因为我们有了房屋的设计图,就能够准确地计算出房屋的占地面积了。
  • 当然,还有一个简单的方式,直接把鼠标移动到类名上即可,它会自动出现一些详细信息:
    示例3
(2)直接计算

直接计算就涉及到结构体的内存对齐规则了,知识C语言方面的知识。在这里也简单的复习一下:

  • 第一个成员在与结构体偏移量为0的地址处。
  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
  • 对齐数 = 编译器默认的一个对齐数与该成员大小的较小值(VS中默认的对齐数为8)
  • 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取较小)的整数倍
  • 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
    我们来举个例子:
    示例4
    根据对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。(VS中默认的对齐数为8),int a的对齐数为4(int a本身大小为4,默认对齐数为8,取较小值);同理,int b对齐数也为4;char c的对齐数为1(char c本身大小为1,默认对齐数为8,取较小值)。 根据结构体总大小为:最大对齐数(所有变量类型最大对齐数与默认对齐数的较小值)的整数倍,这里的成员变量的对齐数最大值为4,和默认对齐数8相比较小,因此最终结构体对齐方式为4个字节,a占4字节,b占4字节,c占4字节(用1个字节,空3个字节)。
为什么需要结构体内存对齐规则?

CPU是一次性读取一定的字节数,我们以这样的一个结构体为例:
示例5
char型占用一个字节,int型占用4个字节,假设CPU一次读取4个字节。

  • 如果是连着存储,那么就是CPU一次读取的4个字节中有一个字节属于char a,另外三个字节属于int b的一部分,b并没有被一下子读取完整,因此需要再读一次,然后将两次读取的结果拼接,然而拼接数据的耗时会大大增加
  • 如果使用内存对齐,那么前4个字节中,有一个字节是char,后三个字节空着,然后接下来的四个字节完整的存储一个int b,CPU一下子就能把b的值读完整,避免了拼接提高了效率,这是一种以空间换时间的方式。

2.类和对象相关的存储方式

刚才在计算的过程中,我们好像只在讨论类中成员变量对应的空间,就算出了对象的大小,但是类里面还有成员函数呢,它们占据空间吗?

  • 我们以这样一段代码为例:
    示例6
    根据上文的计算,这里的对象是12个字节,函数并没有占用空间。其实,这也是很好理解的。成员函数和成员变量不同,它是一个方法。基于同一个类创建出的不同的对象各自的成员变量是自己的,但是操作方法是一样的,是共同的,比如说这里的一个函数,它就是一个打印两个数相加的功能,不管什么对象都一样。就好比一个小区,每家每户的房子是自个儿的,但是那些篮球场,游泳池是大家共用的,没有必要每建一间房,都要配上一个篮球场,游泳池。在这里也一样,每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。
  • 如果一个类中没有成员变量,只有成员函数或者什么都没有,如图所示:
    示例7
    示例8
    没有成员变量的类对象,需要1字节,是为了占位,表示对象存在,并没有存储有效数据。

二、this指针

我们以日期类为例:
示例9
在这个日期类中,我们定义了年、月、日三个成员变量,并且还有初始化以及打印这两个函数。我们再实例化几个对象:
示例10
Date类中有 InitPrint 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?这里,我们就要引入一个新的内容——this指针
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要传递,编译器自动完成。
如图所示:
示例11
比如:

Date d1;
d1.Init(2025, 3, 9);
d1.Print();

这里this指针就是指向的d1,然后通过this指针访问d1里的成员变量。
this指针的特性

  • this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。也就是说this指针在使用时不能指向别的对象,只能指向当前对象,但是可以修改当前对象的内容。
  • 只能在“成员函数”的内部使用
  • this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
  • this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

三、C语言和C++实现一个栈的对比

1.C语言实现

(1)头文件
#pragma once#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int DataType;struct Stack
{DataType* a;int top;int capacity;
};typedef struct Stack Stack;void StackInit(Stack* ps);
void StackPush(Stack* ps, DataType x);
bool StackEmpty(Stack* ps);
void StackPop(Stack* ps);
DataType StackTop(Stack* ps);
int StackSize(Stack* ps);
void StackDestroy(Stack* ps);
(2)源文件
#include"Stack.h"void StackInit(Stack* ps)
{assert(ps);ps->a = (DataType*)malloc(sizeof(DataType) * 4);//先开辟4个数据的空间if (ps->a == NULL)//基本操作,检查动态内存开辟是否成功{perror("malloc fail");return;}ps->top = -1;//top指的是栈顶元素的位置,现在栈中没有插入数据,因此top为-1,待插入数据后,top+1变为0,刚好和数组的下标相对应(第一个数据下标为0)ps->capacity = 4;//表示初始化后栈中能存4个数据
}void StackPush(Stack* ps, DataType x)
{assert(ps);if (ps->top + 1 == ps->capacity)//检查是否需要扩容,top是数组的下标位,我们都知道,数组的下标位是比数组实际数据个数少1的,因此需要top+1{DataType* tmp = (DataType*)realloc(ps, sizeof(DataType) * ps->capacity * 2);if (tmp == NULL){perror("malloc fail");return;}ps->a = tmp;//tmp指向的是调整后内存的起始地址}ps->capacity *= 2;//经过扩容,容量变为原来的两倍ps->top++;//现在是插入数据,栈顶的下标位要+1了ps->a[ps->top] = x;//在栈顶处插入数据
}bool StackEmpty(Stack* ps)//判断栈中是否存在数据,如果为空,则返回1,如果不为空,则返回0
{assert(ps);return ps->top == -1;//当栈为空时,其特点就是栈顶的下标位为-1
}void StackPop(Stack* ps)//栈顶数据出栈
{assert(ps);assert(!StackEmpty(ps));//assert里面的内容为0(或者NULL)时会生效,如果现在想让它生效,则要(!StackEmpty(ps))为0,则StackEmpty(ps)为1,此时就是栈中数据为空的情况ps->top--;//所谓出栈,就是将栈顶的下标位-1,这样在取出元素的时候就取不到已经出了栈顶数据了
}DataType StackTop(Stack* ps)//查看栈顶的元素
{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top];
}int StackSize(Stack* ps)//查看一下栈中有几个元素
{assert(ps);return ps->top + 1;//数组下标位+1为元素个数
}void StackDestroy(Stack* ps)//栈的销毁
{assert(ps);free(ps->a);ps->a = NULL;ps->top = -1;ps->capacity = 0;
}

不难发现,代码量还是很大的,具体细节在数据结构专栏有详细讲解。

2.C++实现

typedef int DataType;
class Stack
{
public:void Init(){_array = (DataType*)malloc(sizeof(DataType) * 3);if (NULL == _array){perror("malloc fail");return;}_capacity = 3;_size = 0;}	void Push(DataType data){CheckCapacity();_array[_size] = data;_size++;}void Pop(){if (Empty())return;_size--;}DataType Top() { return _array[_size - 1]; }int Empty() { return 0 == _size; }int Size() { return _size; }void Destroy(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}
private:void CheckCapacity(){if (_size == _capacity){int newcapacity = _capacity * 2;DataType* temp = (DataType*)realloc(_array, newcapacity *sizeof(DataType));if (temp == NULL){perror("realloc fail");return;}_array = temp;_capacity = newcapacity;}}
private:DataType* _array;int _capacity;int _size;
};

C++中通过类可以将数据以及操作数据的方法(函数)进行完美结合,通过访问权限可以控制那些方法在类外可以被调用,即封装,在使用时就像使用自己的成员一样,更符合人类对一件事物的认知。而且每个方法不需要传递Stack*的参数了,编译器编译之后该参数会自动还原,即C++中 Stack * 参数是编译器维护的,C语言中需用用户自己维护。

本期总结+下期预告

本期内容书接上回,继续讨论类和对象相关知识。下期将为大家带来类和对象中非常重要的部分——构造函数、析构函数等内容!

感谢大家的关注,我们下期再见!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/73460.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LVGL移植到6818开发板

一、移植步骤 1.lv_config.h 配置文件启动 framebuffer 2、lv_config.h 配置文件关闭SDL 2.修改main.c 去掉SDL输入设备 3.修改Makefile 文件启动交叉编译 去掉警告参数 去掉SDL库 4.交叉编译代码 make clean #清空 ⭐ 必须要清空一次再编译&#xff01; 因为修改了 lv_con…

linux系统命令——权限

一、有哪些权限 读&#xff08;r&#xff09;——对应数字4 写&#xff08;w&#xff09;——对应数字2 执行&#xff08;x&#xff09;——对应数字1 二、权限及数字的对应 4对应r-- 2对应-w- 1对应--x 5对应r-x 6对应rw- 7对应rwx 三、文件的基本属性 如图&#…

Django项目之订单管理part3

一.前言 前面两章已经把登录给做完了&#xff0c;这一章节要说的是登录的校验和登录以后的菜单展示&#xff0c;内容还是很多的。 二.菜单和权限 2.1 是否登录 当我们进入其他的页面&#xff0c;我们首先要判断是否登录&#xff0c;这个时候我们就要借助中间件来做session和…

AI大模型测试用例生成平台

AI测试用例生成平台 项目背景技术栈业务描述项目展示项目重难点 项目背景 针对传统接口测试用例设计高度依赖人工经验、重复工作量大、覆盖场景有限等行业痛点&#xff0c;基于大语言模型技术实现接口测试用例智能生成系统。 技术栈 LangChain框架GLM-4模型Prompt Engineeri…

【论文笔记】Contrastive Learning for Compact Single Image Dehazing(AECR-Net)

文章目录 问题创新网络主要贡献Autoencoder-like Dehazing NetworkAdaptive Mixup for Feature PreservingDynamic Feature Enhancement1. 可变形卷积的使用2. 扩展感受野3. 减少网格伪影4. 融合空间结构信息 Contrastive Regularization1. 核心思想2. 正样本对和负样本对的构建…

异步加载错误如何解决

首先是 提供两张图 如果数据过多的情况下我在所内和住家形式频繁的来回切换 导致数据展示的不一样 大家是不是有这样的问题 这个是导致了数据展示有问题的情况 住家的情况本来是没有几层的 下面我帮大家解决一下 // 防止异步延迟 const Noop () > { } const lhl (resDa…

编译支持 RKmpp 和 RGA 的 ffmpeg 源码

一、前言 RK3588 支持VPU硬件解码&#xff0c;需要rkmpp进行调用&#xff1b;支持2D图像加速&#xff0c;需要 RGA 进行调用。 这两个库均能通过 ffmpeg-rockchip 进行间接调用&#xff0c;编译时需要开启对应的功能。 二、依赖安装 编译ffmpeg前需要编译 rkmpp 和 RGA&#xf…

Java多线程与高并发专题——原子类和 volatile、synchronized 有什么异同?

原子类和 volatile异同 首先&#xff0c;通过我们对原子类和的了解&#xff0c;原子类和volatile 都能保证多线程环境下的数据可见性。在多线程程序中&#xff0c;每个线程都有自己的工作内存&#xff0c;当多个线程访问共享变量时&#xff0c;可能会出现一个线程修改了共享变…

207、【图论】孤岛的总面积

题目 思路 相比于 206、【图论】岛屿数量&#xff0c;就是在这个代码的基础上。先遍历边界&#xff0c;将边界连接的岛屿变为0&#xff0c;然后再计算一遍当前为1的岛屿面积。 代码实现 import collectionsn, m list(map(int, input().split())) graph []for _ in range(n…

【GPT入门】第21课 langchain核心组件

【GPT入门】第21课 langchain核心组件 1. langchain 核心组件2.文档加载器 Document loader3.文档处理器3.1 langchain_text_splitters3.3 FAISS向量数据库和向量检索主要作用应用场景4. 对话历史管理1. langchain 核心组件 模型 I/O 封装 LLMs:大语言模型 Chat Models:一般…

应急响应靶机练习-Linux2

1.背景 前景需要&#xff1a;看监控的时候发现webshell告警&#xff0c;领导让你上机检查你可以救救安服仔吗&#xff01;&#xff01; 挑战内容&#xff1a; &#xff08;1&#xff09;提交攻击者IP &#xff08;2&#xff09;提交攻击者修改的管理员密码(明文) &#xff08;…

分享一个免费的CKA认证学习资料

关于CKA考试 CKA&#xff08;Certified Kubernetes Administrator&#xff09;是CNCF基金会&#xff08;Cloud Native Computing Foundation&#xff09;官方推出的Kubernetes管理员认证计划&#xff0c;用于证明持有人有履行Kubernetes管理的知识&#xff0c;技能等相关的能力…

【最新】 ubuntu24安装 1panel 保姆级教程

系统&#xff1a;ubuntu24.04.1 安装软件 &#xff1a;1panel 第一步&#xff1a;更新系统 sudo apt update sudo apt upgrade 如下图 第二步&#xff1a;安装1panel&#xff0c;运行如下命令 curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o …

UE4-UE5虚幻引擎,前置学习一--Console日志输出经常崩溃,有什么好的解决办法

有些差异 这么牛逼的引擎&#xff0c;居然有这种入门级别的问题&#xff0c;一触发清理&#xff0c;大概率(80%)会崩溃 无论虚幻5还是UE4都有这个问题&#xff0c;挺烦人的 实在忍不了了&#xff0c;这次&#xff0c;今天 就想问问有什么好的处理方法么&#xff1f;&#x…

【微服务】Nacos 配置动态刷新(简易版)(附配置)

文章目录 1、实现方法2、配置依赖 yaml3、验证效果 1、实现方法 环境&#xff1a;Nacos、Java、SpringBoot等 主要是在boostrap.yaml中的data-id属性下配置refresh:true来实现动态更新 2、配置依赖 yaml 具体的版本参考官方的说明&#xff1a;官方版本说明 <!--读取boo…

设计模式之备忘录设计模式

备忘录设计模式&#xff08;Memento Pattern&#xff09; 在不破坏封闭的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;保存对象的某个状态&#xff0c;以便在适当的时候恢复对象&#xff0c;又叫做快照模式&#xff0c;属于行为模式备忘录模式实现的方式需要保证被保…

【最后203篇系列】016 Q201架构思考

前言 Q200已经达到了我既定的目标&#xff0c;在最近的3个月&#xff0c;我需要进一步完善&#xff0c;达到可以试产的程度。 在这个过程当中&#xff0c;许多知识和体会一直在变。 qtv200到目前&#xff0c;虽然通过习惯(每晚运行离线策略和比对)方式维持了注意力的集中&…

音视频入门基础:RTP专题(20)——通过FFprobe显示RTP流每个packet的信息

通过FFprobe命令&#xff1a; ffprobe -protocol_whitelist "file,rtp,udp" -of json -show_packets XXX.sdp 可以显示SDP描述的RTP流每个packet&#xff08;数据包&#xff09;的信息&#xff1a; 对于RTP流&#xff0c;上述的“packet”&#xff08;数据包&#…

LLM后训练:解锁大型语言模型推理能力的关键路径

引言&#xff1a;从语言生成到逻辑推理的跃迁 大型语言模型&#xff08;LLMs&#xff09;通过预训练掌握了海量语言模式&#xff0c;但其核心缺陷——幻觉、逻辑断裂、价值观偏差——暴露了单纯预训练的局限性。后训练&#xff08;Post-Training&#xff09;作为预训练后的精修…

9.贪心算法

简单贪心 1.P10452 货仓选址 - 洛谷 #include<iostream> #include<algorithm> using namespace std;typedef long long LL; const int N 1e510; LL a[N]; LL n;int main() {cin>>n;for(int i 1;i < n;i)cin>>a[i];sort(a1,a1n);//排序 LL sum 0…