C/C++基础知识

数据类型

目录

数据类型

基本数据类型

变量所占大小

        char

构造类型

        数组

        1.一维数组

        2.二维数组

        结构体

        联合体

        指针 

         内存的申请与释放

                C++中的new

                malloc

                malloc与new的异同

                C++中的delete

                free

               new和delete是如何实现的

                malloc和free的实现

               被free回收的内存是立即还给操作系统了吗

                calloc与realloc

         指针类型

                数组指针与指针数组

                二级指针

                函数指针

                指针大小

                *的三种作用

        C++引用变量

                声明

                常量引用

                指针的引用

                引用与函数

                引用与指针的区别

        修饰符

                static的用法和作用

                静态变量什么时候初始化

                指针与const的用法


基本数据类型

变量所占大小

X64X86
char1字节1字节
short2字节2字节
int4字节4字节
long8字节4字节
long long8字节8字节
float4字节4字节
double8字节8字节
long double 通常16字节通常8字节

        char

        分为三类型:

        1.char:标准类型

        2.unsigned char:无符号char(0~255)

        3.signed char:有符号char(-128~127)

构造类型

        数组

        1.一维数组

                字符串/字符数组

char arr1[] = "hello"; 字符串:结尾有'\0'终止符,arr1占6字节
char arr2[] = {'H', 'e', 'l', 'l', 'o'}; 字符数组:结尾无'\0',arr2占5字节
'\0'影响printf等输出,输出结果为'\0'之前

                字符串的申明方式

                1.静态分配,编译时在栈上分配好内存

                2.字符串常量

                3.动态分配内存(malloc和new)

                4.自动分配,在局部函数中

                操作函数

size_t strlen(const char *str) 返回字符串长度,不包含'\0'
char *strcpy(char *dest, char *src) 把src复制给dest
char *strncpy(char *dest, const char *src, size_t n) 把src复制给dest前n个字符
char *strcat(char *dest, const char *src) 把src添加到dest的结尾
char *strncat(char *dest, const char *src, size_t n) 把src前n个字符添加到dest结尾
int strcmp(const char *str1, const char *str2) 比较字符串是否相同,成功返回0,失败返回不同个数
int strncmp(const char *str1, const char *str2, size_t n) 比较前n个字符串,返回与strcmp相同
char *strchr(const char *str, int c) 返回c第一次在str出现的地址
char *strrchr(const char *str, int c) 返回c最后一次在str出现的地址
char *strstr(const char *haystack, const char *needle) 返回needle在haystack第一次出现的地址

                地址

char arr[10] = "Hello";
arr与&arr[0]所表示是一样的
&arr是整个数组的地址,类型是char (*)[10],表示10个指向char元素的指针

                指针数组与数组指针

指针数组,包含3个char的指针
char *ptr_arry[3]
数组指针,指向一个包含3个char的数组
char (*arry_ptr)[3]
        2.二维数组

                初始化

1.没什么好说的
int array[3][4];
2.编译器自动分配
int array[][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}
};
3.分配动态内存
int rows = 3;
int cols = 4;
int **array = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {array[i] = (int *)malloc(cols * sizeof(int));
}
4.使用stl容器
int rows = 3;
int cols = 4;
std::vector<std::vector<int>> array(rows, std::vector<int>(cols));

                地址 

                &a[1],&a[0]==a;一维数组地址

                &a[0][1],&a[0][0] == a[0];元素地址

                &a;二维数组地址

        结构体

                声明

1.默认声明
struct Point {int x;int y;
};
C++的结构体class,为兼容c,保留了struct
2.定义并声明实例
struct Point {int x;int y;
} p1, p2;
3.结构体别名
typedef struct {int x;int y;
} Point;
Point p1; 
C++默认声明,创建实例时不需要声明结构体struct或class

                结构体大小

struct Example {char a;    // 1 byteint b;     // 4 byteschar c;    // 1 byte
};

                以上面为例,变量存储地址为自身所占字节大小的倍数,设从0x00开始,char占1个字节,地址在0x00,b占4字节,因为地址要是自身字节大小的整数倍,所以地址在0x04;c占1个字节,地址在0x08,所以Example结构体的大小为9字节。

                其中,c特有的位域,变量+:+位数,用于修改变量大小,节省内存空间。计算方式为同类型变量合并,不足该变量字节大小的部分自动填充,不同类型的变量按结构体的计算方式存入地址。

                链表

                单链表:简单,节点只包含指向下一个节点的指针。

                双向链表:支持双向遍历,节点包含指向前一个和下一个节点的指针。

                循环链表:尾节点指向头节点,形成一个环,适合需要循环访问的情况。

                C++中class与struct区别

                (1)相同点

                都能拥有成员函数,公有和私有部分;class可以实现的struct也可以实现。

                (2)不同点

                struct默认公有,class默认私有;struct默认公有继承,class默认私有继承。 

                (3)C++的struct与C的区别

                C语言中struct是自定义数据类型;C++中是抽象数据类型,支持成员函数的定义(C++中可以继承和实现多态)

                C语言中struct没有访问权限设置,成员只能是变量,但可以存入函数地址,数据不能被隐藏。

                C++设置了访问权限,功能与class一样,默认是public访问。

                C语言声明实例时必须在前面加struct,除非定义结构体时使用typedef。C++不需要,结构体struct在C++中被当作特例。

        联合体

                联合体声明     

union Data {int i;float f;char str[20];
};

                联合体大小计算

                联合体的大小是其最大的数据成员大小的整数倍再满足编译器的内存对齐要求的最小倍数。以上面为例,联合体最大成员时char str[20],则联合体大小为20字节,若内存对齐要求为4字节,则不变;若为8字节,则填充4字节为24字节。

                判断大小端

#include <iostream>
union data{int a;char b;
}void main()
{data udata;udata.a = 0x12345678;if(udata.b == 0x78)printf("Little-Endian\n");else if(udata.b == 0x12)printf("Big-Endian\n");elseprintf("Unkonwn Endian\n");
}

        指针 

         内存的申请与释放
                C++中的new
分配内存,构造一个整数
int* ptr = new int;
分配内存,构造函数参数进行构造
MyClass* ptr = new MyClass(arg1, arg2);
分配数组内存
MyClass* array = new MyClass[5];
或者memset设置内存初始值
使用std::nothrow,new失败时返回null
                malloc
type p = (type)malloc(分配大小)
分配失败时返回null
                malloc与new的异同

                相同点

                都可以动态申请内存

                不同点

                new是C++操作符,支持重载,还会调用构造函数;malloc是C/C++的标准函数。

                new是类型安全的,malloc不安全。

                new返回具体指针,malloc返回void型指针,需要类型转换。

                new自动计算分配内存大小,malloc需要手动计算。

                new是封装了malloc。

                C++中的delete

                释放内存 

释放单个对象的内存
MyClass* obj = new MyClass(); // 用 new 分配对象
delete obj; // 释放分配的对象内存
释放数组的内存
MyClass* array = new MyClass[10]; // 用 new[] 分配对象数组
delete[] array; // 释放分配的数组内存
一个new对应一个delete
释放内存后需要将指针指向空
delete null是安全的
                free

                释放内存

int *array = (int *)malloc(10 * sizeof(int));
free(array);
一个malloc对应一个free
内存释放后将指针指向null,避免产生野指针
free(NULL)会崩溃
               new和delete是如何实现的

                new的实现过程:对简单的函数直接使用operator new函数;对复杂的数据结构调用operator new函数,分配足够大的原始为类型化的内存,运行该类型的构造函数并传入初始值,最后返回该对象的指针。

                delete的实现过程:简单数据类型直接调用free;对复杂的数据结构对指针指向的对象运行析构函数,再用operator delete函数释放对象所使用内存。

                new[]一个数组对象,需要知道数组的长度,会多分配4个字节,实际的数组所占内存为p-4;delete[]操作会取出这个数,知道要调用多少次析构函数。

                malloc和free的实现

                这两个函数是由brk、mmp和munmap这些系统调用实现的。

                brk是将堆顶的指针向高位移动,获得新的内存空间。mmap是在进程的虚拟地址空间(堆和栈中间,称为文件映射区)中找到一块空闲的内存块。这两种都是分配虚拟内存,没有分配实际的物理内存。在第一次访问已分配的虚拟地址空间,发生缺页中断(当程序访问的虚拟内存页面不存在物理内存时,会触发缺页中断),操作系统分配物理内存,建立虚拟内存与物理内存的映射关系。

                malloc分配内存时,当分配内存小于128k,则使用brk在堆顶向高地址移动指针;当分配的内存大于128k时,使用mmap在虚拟地址空间寻找一块空闲内存。brk分配内存需要等高地址的内存释放后才能释放,而mmap分配的内存可以单独释放。当最高地址空间的空闲内存超过128K,则会执行内存紧缩。    

               被free回收的内存是立即还给操作系统了吗

                不是的,被free回收的内存会用双链表ptmalloc保存,当下次申请内存的时候就尝试再内存中寻找合适的返回,避免反复的系统调用,同时tpmalloc也会尝试合并小块内存,防止产生过多内存碎片。

                calloc与realloc

                calloc省去了人为空间计算,calloc申请的空间的初始值是0;realloc给动态分配的空间分配额外的空间。

                深拷贝和浅拷贝

                浅拷贝

class a{public:char *data;a(const char* str){data = new char[strlen(str)+1];strcpy(data, str);}a(const a &other) : data(other.data) {} //浅拷贝构造函数a();~a();
}int main()
{a a1("hello world!");a a2 = a1;return 0;
}

               a1直接赋值给a2,实际a2使用的内存与a1使用的是同一块,a1内存被回收后,a2会访问无效内存,发生未定义行为。

                深拷贝

class a{public:char *data;a(const char* str){data = new char[strlen(str)+1];strcpy(data, str);}a(const a &other){data = new char[strlen(other.data)+1];strcpy(data, other.data);}//深拷贝构造函数a();~a();
}int main()
{a a1("hello world!");a a2 = a1;return 0;
}

                a2不仅复制了a1的值,还分配了独立内存 。

         指针类型
                数组指针与指针数组

                数组指针:数组是指针;指针数组:成员是指针。

                二级指针

                一级指针指向某数据类型的内存地址,二级指针指向一级指针的内存地址。

                函数指针
int (*funcPtr)(int, int);

                它用于指向函数的内存地址。

                指针大小

                32位一般是4字节,64位一般是8字节。地址+1是加了一个类型的大小。

                *的三种作用

                (1)解引用运算符:*指针变量,表示地址操作符,取内容

                (2)指针申明:表示指针变量

                (3)运算:表示乘

        C++引用变量
                声明
int b = 4;
int &a = b;

                是对已存在变量的别名。

                常量引用
const int &value

                值不允许修改。

                数组引用与指针一样。

                指针的引用
int *a = new int;
int *(&b) = a;
                引用与函数

                不要引用局部变量。

                引用与指针的区别

                (1)引用声明的初始化,指针不用马上初始化

                (2)引用不能指向空,指针可以

                (3)引用初始化后不能指向其他变量,指针可以

                (4)引用效率高

                (5)引用更安全,指针可以偏移

                (6)指针更灵活,直接操作地址;指针更通用,C/C++都可以。

        修饰符

                static的用法和作用

                1.隐藏

                2.保持变量内容的持久,即改变变量的生命周期。将static修饰的变量存入静态数据区(全局区)。

                3.默认初始化为0。

               4.在C++中类成员声明static:

                (1)函数体内static变量的作用范围为该函数体,内存只分配一次。

                (2)在模块内的static全局变量只能被该模块的函数访问。

                (3)模块内的static函数只能被该模块的函数调用。

                (4)类中的static成员变量属于类所有,对类的所有对象只有一份拷贝,该变量的初始化要在类外。

                (5)类中的static成员函数属于类所有,这个函数没有this指针,只能访问类中的静态成员变量。

                类内:               

                (6)static类对象要在类外初始化,因为static修饰的变量先类存在。

                (7)static修饰的类成员属于类不属于对象,所以没有this指针,this指针是指向本成员的指针,所以无法访问非static的类成员。

                (8)static成员函数不能被virtual修饰,static成员不属于任何对象和实例,virtual加上没有任何意义;静态成员没有this指针,虚函数的实现是对每个对象分配vptr指针,而vptr指针由this指针调用,所以不能为virtual。虚函数的调用关系:this->vptr->ctable->virtual function。

                静态变量什么时候初始化

                1.初始化只有一次,在主程序前编译器已经分配好内存。

                2.静态局部变量与全局变量一样存在全局区。在C中,初始化发生在执行代码前,编译阶段分配内存后,就会初始化,所以C语言中无法用变量初始化静态局部变量;程序结束,变量所处的全局内存会被回收。

                3.在C++中,初始化在执行相关代码时,主要时C++引入对象后,要进行初始化必须要用构造函数或析构函数,构造和析构函数一般需要执行相关的程序,而非简单分配内存。所以C++规定在首次使用到全局或静态变量时进行构造,并通过atexit()管理。在程序结束时,根据构造的顺序反方向析构,所以C++中的静态局部变量可以用变量初始化。

                指针与const的用法

int val = 10;
指针常量
int* const a = &val;
常量指针
const int *b = &val;

                指针常量是指指针是常量,即指针指向的地址不可变,但指向地址的内容可变。

                常量指针是指指针指向的内容不可变,地址可变。

剩下的明天写。

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

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

相关文章

面试题:为什么 一般 weight 选择对称量化,activation 选择非对称量化?

模型的剪枝是为了减少参数量和运算量&#xff0c;而量化是为了压缩数据的占用量。 量化概念 所谓的模型量化就是将浮点存储&#xff08;运算&#xff09;转换为整型存储&#xff08;运算&#xff09;的一种模型压缩技术。 优势&#xff1a; 可以提升计算效率&#xff1b;减少…

泛微开发修炼之旅--40考勤管理篇:根据班次规则、考勤组规则(含固定值和排班制),在三方系统中获取考勤签到数据,并同步到考勤管理中的解决方案

一、需求描述 我们最近在项目上遇到了一个需求&#xff0c;需要将工厂门禁刷脸数据&#xff0c;通过考勤管理配置的规则&#xff0c;获取到对应的考勤签到数据&#xff0c;依次作为上下班打卡的时间&#xff0c;以此作为员工每天考勤的依据&#xff0c;客户的考勤比较复杂&…

《python程序语言设计》第6章15题财务应用程序:打印税款表。利用程序清单4-7的代码

6.15 打印税款表 def computeTax(status_n, income):tax 0if status_n 0:if income < 8350:tax income * 0.10elif income < 33950:tax 8350 * 0.10 (income - 8350) * 0.15elif income < 82250:tax 8350 * 0.10 (33950 - 8350) * 0.15 (income - 33950) * 0.…

Vue2生命周期+八个钩子函数解析

一.vue生命周期的几个基本概念和常见问题 1.什么是vue的生命周期? 答案&#xff1a;一个vue实例从创建到销毁的过程。 2.vue生命周期有哪几个阶段? 答案&#xff1a;生命周期有四个阶段 分为以下四个阶段&#xff08;有的可能叫法不一样&#xff09; 创建 挂载更新销毁…

《九界ol游戏源码》(游戏源码+客户端+服务端+工具+视频教程)喜欢研究游戏源码的看过来...

《九界》游戏以网络同名热门小说为文化蓝本&#xff0c;构筑了一个地海陆空四维冒险的庞大游戏世界。《九界》以“团队修真”为核心研发理念&#xff0c;引擎采用OGRE引擎&#xff0c;GUI的设计采用CEGUI&#xff0c;游戏设计&#xff0c;地图&#xff0c;音效都是花费了相当的…

哈默纳科HarmonicDrive谐波减速机的使用寿命计算

在机械传动系统中&#xff0c;减速机的应用无处不在&#xff0c;而HarmonicDrive哈默纳科谐波减速机以其独特的优势&#xff0c;如轻量、小型、传动效率高、减速范围广、精度高等特点&#xff0c;成为了众多领域的选择。然而&#xff0c;任何机械设备都有其使用寿命&#xff0c…

Python爬虫-中国汽车市场月销量数据

前言 本文是该专栏的第34篇,后面会持续分享python爬虫干货知识,记得关注。 在本文中,笔者将通过某汽车平台,来采集“中国汽车市场”的月销量数据。 具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。废话不多说,下面跟着笔者直接往下看正文详细内容。(附…

Java笔试面试题AI答之线程Thread(1)

答案来自 Kimi AI 目录 1. 进程和线程的区别&#xff1f;2. Java语言创建线程的方式有哪些&#xff1f;3. Java线程有哪几种可用状态&#xff1f;4. Java同步方法和同步代码块的区别&#xff1f;5. 在监视器(Monitor)内部&#xff0c;如何做线程同步的&#xff1f;6. 什么是死…

硅纪元视角 | 语音克隆突破:微软VALL-E 2,Deepfake新纪元!

在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展&#xff0c;捕捉行业动态&#xff1b;提供深入的新闻解读&#xff0c;助您洞悉技术背后的逻辑&#xff1b;汇聚行业专家的见解&#xff0c;…

Web前端知识视频教程分享(五) Bootstrap

资料下载地址&#xff1a; https://545c.com/f/45573183-1336822373-45bb4f?p7526 (访问密码: 7526)

Flink内存管理机制

前言 在Flink的后台界面&#xff0c;可以看到整个Flink的内存情况。 如JobManager的内存情况&#xff1a; TaskManager的内存情况 一、Flink内存管理 Flink TaskManager内存组成整体结构图如下&#xff1a; 二、总内存管理 三、JobManager内存管理内存管理 四、TaskManager内…

vue3前端架构---打包配置

最近看到几篇vue3配置项的文章&#xff0c;转载记录一下 Vue3.2 vue/cli-service 打包 chunk-vendors.js 文件过大导致页面加载缓慢解决方案-CSDN博客文章浏览阅读2k次&#xff0c;点赞8次&#xff0c;收藏9次。Vue3.2 vue/cli-service 打包 chunk-vendors.js 文件过大导致页…

Lago - 使用 ClickHouse 扩展事件引擎

本文字数&#xff1a;4540&#xff1b;估计阅读时间&#xff1a;12 分钟 作者&#xff1a;Mathew Pregasen 本文在公众号【ClickHouseInc】首发 本周&#xff0c;我们欢迎来自 Lago 的一篇博客文章&#xff0c;介绍了他们如何使用 ClickHouse 扩展一个事件引擎&#xff0c;并在…

学习react-Provider解决props需要层层传递问题

1.组件数据传递问题 数据传递&#xff1a;A(顶级组件&#xff09;-》B组件&#xff08;子组件&#xff09;、C组件&#xff08;孙子组件&#xff09;…很多组件 这样得通过props层层传递到下面的组件 还有另一种解决方法&#xff0c;即通过全局对象来解决&#xff0c;使用Prov…

搭建自己的金融数据源和量化分析平台(二):读取上交所股票列表

我在上交所没发现上交所有像深交所一样的一键下载股票xls文档的按钮&#xff0c;因此上交所的股票列表读取就会比较麻烦。总体思路是查出来所有股票的代码之后根据股票代码逐一发起HTTP请求读取公司英文名、总股本、流通股本等详细信息&#xff0c;这就导致上交所爬虫的网络交互…

堆的实现-适用于算法竞赛

首先讲一下能够实现的操作。 插入一个数查找最小值删除最小值删除任意一个元素修改任意一个元素 什么是堆&#xff1f; 堆其实是一棵完全二叉树。 即处理叶子节点和倒数第一层节点&#xff0c;其他节点都有两个子节点&#xff0c;而且顺序是从上到下&#xff0c;从左到右。 …

使用VMware安装Linux虚拟机

一、下载 通过百度网盘分享的文件&#xff1a;CentOS系统安装包 链接&#xff1a;https://pan.baidu.com/s/1_eqYl8HcNt2GcGDjgOElgg 提取码&#xff1a;cu07 二、安装 &#xff08;1&#xff09;双击打开软件 &#xff08;2&#xff09; 创建新的虚拟机 &#xff08;3&…

PyQt ERROR:ModuleNotFoundError: No module named ‘matplotlib‘

Solution:打开cmd输入指令下载malplotlib pip install matplotlib

Kubernetes:优势、场景与特点

Kubernetes:优势、场景与特点 1、优势2、适应场景3、特点💖The Begin💖点点关注,收藏不迷路💖 1、优势 容器编排:自动化管理容器生命周期,简化运维。轻量级开源:降低部署成本,易于集成到现有系统。弹性伸缩:根据业务负载自动调整资源,确保应用性能。负载均衡:高…

微软第四季度财报预览:增长动力追踪

微软公司即将在2024年7月30日&#xff08;周二&#xff09;美国市场收盘后发布第四季度财务结果。 微软的收益 - 预期如何 美股券商开户通道 市场预计&#xff0c;微软即将到来的2024年第四季度的收入将年增长14.5%&#xff0c;达到644亿美元&#xff0c;高于2023年第四季度…