C++ 基础知识

2023-11-04

一、 语法:

1.指针常量/常量指针

  1. 指针常量:顾名思义,指针是一个常量, 所以指针的指向不能改变,指针指向的值可以改变。
  2. 常量指针:顾名思义,指向常量的指针,指针的指向可以改变,指针指向的值不能改变。

2. 内存模型

  1. 代码区:
    1. 用户写的所有代码都会放在代码区,二进制格式。
    2. 代码区是共享的:相对于线程来说,代码区内的所有代码都是共享的,因为有可能用户会多次执行exe文件,开辟多次线程,所有多个线程可以共享同一份代码数据即可运行程序。
    3. 代码区是只读的:使其只读的原因是防止程序意外地修改了它的指令。
  2. 全局区:
    存放全局变量静态变量以及常量,该区域的数据在程序结束后由操作系统释放.
    1. 全局变量:只要不是写在函数体中的变量都称之为全局变量。
      在这里插入图片描述

    2. 静态变量:
      在普通变量前加上static,属于静态变量。局部静态变量和全局静态变量都属于全局区:
      在这里插入图片描述

    3. 常量:

      1. 字符串常量:
        只要是用” xxx” 的都是字符串常量

      2. const修饰的量:
        const修饰的全局变量:属于全局区
        在这里插入图片描述

        cosnt修饰的局部变量:在方法体中属于局部变量不属于全局区

总结:C++在程序运行前需要在内存中开辟代码区、全局区。全局区存放全局变量,static修饰的静态变量,常量(字符串常量,全局常量)

  1. 栈区:
    编译器自动分配释放, 存放函数的参数值,局部变量等。
    注意事项:不要返回局部变量的地址,因为方法体中的局部变量是分配在栈区中的,只要方法执行完后,栈区开辟的数据空间就由编译器自动释放
    在这里插入图片描述

  2. 堆区:
    程序员分配和释放,若程序员不释放,程序全部结束时由操作系统回收
    利用new在堆区开辟内存:
    在这里插入图片描述
    利用delete释放内存
    在这里插入图片描述

总结:不同区域存放的数据,赋予不同的生命周期, 给我们更大的灵活编程

3. 引用

  1. 引用的本质:引用的本质就是给一个变量起别名
    在这里插入图片描述 在这里插入图片描述
    引用必须在定义的时候就初始化。引用在初始化后,不可以改变
    在这里插入图片描述 在这里插入图片描述

  2. 引用的底层实现:引用的本质就是定义一个指针常量来指向a,所以这也能解释引用不能修改的原因。
    在这里插入图片描述

  3. 引用在C++中的使用:

    1. 引用在函数中做值传递的应用:
      函数中参数的值传递一般有三种方式:
      在这里插入图片描述

      值传递:
      在这里插入图片描述
      地址传递:
      在这里插入图片描述

      引用传递:
      在这里插入图片描述
      常量引用作为新参:表示传来的参数不能修改,只能读取:
      在这里插入图片描述

    引用传递和地址传递都能实现数值交换的需求,主要原理在于他们传递的都是地址。通过地址操作原来的栈中的a、b数据。而通过值传递则不能实现,因为值传递还是会在栈中分配另一份空间,函数中也是操作另一份空间中的内容,原空间中的值不变。

    1. 引用在函数中做返回值的应用:
      注意:不能将局部变量的引用返回
      在这里插入图片描述
      引用可以作为函数的左值:
      在这里插入图片描述

4. C++中面向对象的三大特性

  1. 封装:

    1. 封装的意义以及访问权限:
      将属性和行为作为一个整体,表现生活中的事物。可以给属性和行为加以权限控制
      三种权限
      ①公共权限 public 类外可以访问 子类继承能访问
      ②保护权限 protected 类外不可以访问 子类继承可以访问
      ③私有权限 private 类外不可以访问 子类继承不可以访问

    2. 类的构造与析构:

      在这里插入图片描述
      //拷贝构造
      Person p3 = Person(p2);
      Person p5 = p4;

    3. 深度拷贝和浅拷贝:
      简单来说浅拷贝就是在对象进行拷贝的时候对对象中的属性进行简单的赋值操作,例如对象L1属于L类,L1中有一个属性m是指向在堆区开辟的一块内存空间。当调用L L2(L1)进行拷贝操作时,由于是浅拷贝,所以直接将L1中的值赋给L2,故L2中的m属性会直接将L1中的m属性的值拷贝过来,那么最终L1、L2的m属性都指向堆区的同一份空间。如果哪天L1进行析构函数的调用,将自身的所有属性都释放掉,包括L1.m指向的那一块堆区空间。那么L1释放掉后,若L2再去执行析构时也会和L1一样去释放自身的所有属性,由于L1已经把堆区那一片空间释放掉了,所以L2再去释放就会报错。根本原因在于L2是进行浅拷贝的L1值,导致L2、L1指向同一份空间。正确的做法是应该采用深拷贝,L2在拷贝L1时,同样给L2.m属性分配一块堆区空间
      编译器默认提供的拷贝方法就是浅拷贝

    4. 类中的静态成员
      所有对象共享同一份数据,在编译阶段分配内存,类内声明,类外初始化
      (1)类的静态成员是属于类而不属于对象,所以他不是类的单个对象所有。
      (2)静态成员只存在一个,不像普通的成员,每创建一个对象,就会创建一组普通的成员。
      (3)父类中定义了静态成员,则整个继承体系中只有一个这样的成员,无论派生出多少个子类。静态成员是存储在全局区的。
      在这里插入图片描述

    5. this

      1. C++中,类内的成员变量和成员函数分开存储。只有非静态成员变量才属于类的对象上。因为C++中成员变量和成员函数是分开存储的,类中每一个非静态函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码,那么问题是:这一块代码是如何区分那个对象调用自己的呢?c++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象。this指针是隐含每一个非静态成员函数内的一种指针,this指针不需要定义,直接使用即可。
      2. this指针的用途:
        当形参和成员变量同名时,可用this指针来区分。
        在类的非静态成员函数中返回对象本身,可使用return *this。
      3. C++中允许空指针调用成员函数,前提是该方法中没有用到this。依据上面所讲,C++中所有对象的方法都是统一放在一个地方,当某个对象调用方法时会隐含的将this指针传入,如果方法中用到了该对象的属性,那么会默认的用this去访问,若指针为空那么this就访问不到。
        在这里插入图片描述 在这里插入图片描述
        因为showPersonAge中访问了非静态成员变量m_Age,而p又没有初始化,所以this = NULL。最终访问错误。
    6. 常函数与常对象

      1. 常函数:
        成员函数后加const后我们称为这个函数为常函数
        常函数内不可以修改该类的对象中成员的属性
        成员属性声明时加关键字mutable后,在常函数中依然可以修改
      2. 常对象:
        对象后面加const后称之为常对象,常对象不能修改对象中的属性值,并且常对象只能调用常函数。
    7. 友元
      生活中你的家有客厅(Public),有你的卧室(Private)客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去但是呢,你也可以允许你的好闺蜜好基友进去。在程序里,有些私有属性也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术友元的目的就是让一个函数或者类访问另一个类中私有成员友元的关键字为 friend友元的三种实现。

    8. 运算符重载
      在这里插入图片描述

  2. 继承:
    继承的语法:class 子类 : 继承方式 父类
    继承方式一共有三种,子类B继承父类A以不同的方式继承会得到不同的效果
    在这里插入图片描述
    公共继承:A中属性的访问权限到了B中还是不变。
    保护继承:A中private变量访问权限到了B中不变,其他的都变为protect
    私有继承:A中所有的属性都变为private

    注:子类会把父类无论什么访问权限的属性都继承下去。
    如果有子类中有同名的成员属性,那么想要访问父类中的属性就必须添加作用域来调用:
    在这里插入图片描述
    构造、析构顺序:继承中是先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反。

  3. 多态:

    1. 多态问题涉及到地址早绑定、晚绑定问题。
      地址早绑定:在编译阶段就确定了函数地址。
      地址晚绑定:如果想要地址晚绑定则需要指定virtual关键字
      在这里插入图片描述

    2. 多态满足条件:
      ①有继承关系
      ②子类重写父类中的虚函数
      ③父类指针或引用指向子类对象

    3. 动态多态底层实现原理
      我们已经知道:类的成员函数不属于某个对象,该函数是放在代码区。
      在这里插入图片描述 在这里插入图片描述
      当Animal类中的speak()方法没有加virtual关键字时,调用sizeof(Animal)结果是1,因为C++编译器会给每个空对象也分配一个字节空间,为了区分空对象占内存的位置,每个空对象也应该有一个独一无二的内存地址
      而如果加上virtual关键字,那么c++会为该类维护一个虚函数表(vftable),并用一个虚函数表执政(vfptr)指向该表
      在这里插入图片描述
      所以只要类中有虚函数,那么c++就会开辟一个空间vftable存放这些虚函数的地址如&WLM::fun1(),&WLM::fun2(),并且生成一个vftptr指向该表,将vftptr隐含的保存到该类中,所以sizeof(WLM)=8 多出来一个vftptr的空间
      在这里插入图片描述
      如果发生继承,那么子类中也会将该vfptr也复制一份到子类对象中
      在这里插入图片描述———>在这里插入图片描述
      当子类重写父类中的虚函数时,子类中的虚函数表内部会替换成子类的重写后的虚函数地址。
      在这里插入图片描述
      总结:因为我们在父类中写了virtual虚函数,父类的类内部结构就会发生变换,生成了一个vfptr虚函数指针,指向虚函数表,表中记录了类中的虚函数入口地址,当子类继承父类后,子类内部也会有一个虚函数指针,同样也指向属于子类的虚函数表。若子类重写了父类中的虚函数,那么子类中的虚函数表中的虚函数入口地址则被子类替换成重写后的虚函数入口地址。如果发生多态,则调用的则是虚函数表中子类重写的虚函数。

5. 纯虚函数和抽象类

  1. 纯虚函数:
    在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数
    纯虚函数语法:virtual 返回值类型 函数名 (参数列表)= 0
    当类中有了纯虚函数,这个类也称为抽象类
  2. 虚析构的作用:
    当我们实现多态时,如果子类中的属性有指向某块堆区,delete时是不会走子类中的析构,而是会去走父类中的虚构函数
    在这里插入图片描述
    如上:Animal animal 实现多态,但delete animal不会走Cat中的虚构
    在这里插入图片描述 在这里插入图片描述
    解决方式:将父类中的析构函数改为虚析构
    在这里插入图片描述 —>在这里插入图片描述
    这样 delete animal 后,就会走子类Cat的虚析构函数。

6. 文件操作

  1. 定义:
    程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放,所以需要通过文件可以将数据持久化。
    C++ 中对文件的操作需要包含头文件 < fstream >
    文件类型分为两种:

  2. 文件类型:
    文本文件 - 文件以文本的ASCII码形式存储在计算机中
    二进制文件 - 文件以文本的二进制形式存储在计算机中,用户一般不能直接读懂
    操作文件的三大类:
    < ofstream>:写操作
    < ifstream>: 读操作
    < fstream>: 读写操作

  3. 文件操作步骤:
    ①包含头文件:#include < fstream >;
    ②创建流对象:ofstream ofs; 或 ifstream ifs;
    ③打开文件: ofs.open(“文件路径”,打开方式);
    在这里插入图片描述
    ④读/写 数据:ofs << “写入的数据”;
    ⑤关闭文件: ofs.close();

7. 模板与泛型

  1. 函数模板:
    普通函数与函数模板区别:
    ①普通函数调用时可以发生自动类型转换(隐式类型转换)
    ②函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换。如果利用显示指定类型的方式,可以发生隐式类型转换
    建议使用显示指定类型的方式调用函数模板,因为可以自己确定通用类型T
    ④如果函数模板和普通函数都可以实现,优先调用普通函数,可以通过空模板参数列表来强制调用函数模板
    在这里插入图片描述
    ⑤函数模板也可以发生重载,如果函数模板可以产生更好的匹配,优先调用函数模板
    在这里插入图片描述
    在这里插入图片描述

  2. 类模板:用template+typename 或 template+class都行:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    类模板中成员函数创建时机:
    普通类中的成员函数一开始就可以创建,类模板中的成员函数只在调用时才创建
    在这里插入图片描述

  3. 类模板作为函数参数的调用更加优雅:
    在这里插入图片描述

  4. 类模板与继承:
    当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
    如果不指定,编译器无法给子类分配内存
    如果想灵活指定出父类中T的类型,子类也需变为类模板
    在这里插入图片描述

  5. 类模板分文件编写:
    类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
    将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制

8. STL

SLT六大组件:容器、算法 、迭代器、仿函数、适配器、空间配置器

  1. 容器:vector、list、deque、set、map等

    1. vector:
      在这里插入图片描述
      向容器中插入数据:v.push_back()
      遍历的三种方法:
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      vector与数组的区别:不同之处在于数组是静态空间,而vector可以动态扩展。并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。

    2. list

    3. deque

    4. set

    5. map

  2. 算法

  3. 迭代器

  4. 仿函数

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 基础知识 的相关文章

随机推荐

  • 看了一次strongswan ipsec的设置.

    看了一次strongswan ipsec的设置 这次的设置要求是 Linux 中 strongwans与hillstone防火墙 stoneOS 建立ipsec连接 network network进行通信 要求Linux可以同时与多台防火墙
  • 从2018年以太坊统计数据看区块链发展趋势

    今年6月 我们发布了 以太坊网络状态 重点介绍了整个网络的一些关键数据和统计数据 六个月后 即将在2018年结束时 我们处于长期 加密货币冬天 的尾声 2017年末至今的市场波动已经引起了区块链行业的普遍关注 然而 仔细研究这些数字可以发现
  • Python实现根据磁盘剩余空间对磁盘多次写入和擦除

    实现根据磁盘剩余容量 对剩余容量 预留了1GB 进行多次的写入和删除数据 次数为变量counts 每次写入1GB的数据 即变量data 多次操作 以实现上述功能 通过更改taskTimes变量可以多次写入和删除 from datetime
  • 基于STM32的智能电子秤设计

    硬件设计 本设计是一款基于STM32单片机的电子秤系统 随着科学技术的不断发展 传统的机械秤逐渐被电子秤所取代 相比于计量不精确 费时费力的机械秤 电子秤采用在方便快捷的同时 又保证了结果的准确性 本次设计采用STM32单片机作为处理器 控
  • 03智慧安防

    一张图读懂一个产业之智慧安防 自2015年起 安防行业逐渐引入人工智能技术 智慧安防 一词开始进入大众视野 伴随着政府 平安城市 天网工程 雪亮工程 等项目不断推出 智慧安防快速成为智慧城市应用中落地情况较好 技术与服务相对成熟的领域之一
  • java 实现部门树_Java实现部门模块开发

    一 新增部门接口开发 1 1 DeptParam java 1 2 LevelUtils java 1 4 1 导入 commons lang3 依赖包 1 2 2 实现LevelUtils开发 1 3 在 com yuluomoshang
  • 物联网设备获取北京时间、年月日、星期几,GMT格林威治标准时间转换为北京时间,授时api Fiddler抓包调试

    1 获取北京时间 年月日 授时api 苏宁获取北京时间的api不要太方便 http quan suning com getSysTime do 使用 Fiddler抓包调试 查看HTTP返回报文 双击左侧抓取到的HTTP返回报文 使用 Sy
  • 同步异步BUCK研究

    目录 一 同步时钟 二 异步BUCK电路 1 基本公式推导 2 电感选型计算 三 同步BUCK电路 四 同步异步BUCK电路对比 前言 在硬件设计中 电源模块基本都会接触到 DC DC拓扑电路又是最常见的 所以深入理解DC DC电路至关重要
  • 轻松成为设计高手

    目录 2 Verilog语言基础 2 1 三种描述方法 2 Verilog语言基础 2 1 三种描述方法 1 数据流描述 assign连续赋值语句 2 行为描述 过程赋值语句 always和initial过程块 3 结构化描述 实例化已有的
  • 微服务(SpringCloud)

    1 什么是微服务 将一个大项目中各个业务代码进行拆分 拆分成多个互不相干小项目 每个项目完成自己特有的功能 而且可以通过调用别的项目完成整体功能 2 SpringCloud 是由Spring提供的一套能够快速搭建微服务框架程序的框架集 也被
  • WEB漏洞测试(二)——HTML注入 & XSS攻击

    上一篇介绍了我们安装BWAPP来完成我们的漏洞测试 在BWAPP中 将HTML Injection和XSS做了非常详细的分类 那么为什么要将两个一起讲呢 归根结底 我觉得这两个分明是一个玩意 充其量是攻击的方式不一样 我们先来介绍一下这两种
  • Electron入门应用打包exe(windows)

    最近在学习nodejs 得知Electron是通过将Chromium和Node js合并到同一个运行时环境中 用HTML CSS和JavaScript来构建跨平台桌面应用程序的一门技术 对于之前一直从事flash AIR桌面应用开发的我迫不
  • 【网络】交换机 VLAN 网关 路由器

    网关 含义 网间连接器 协议转换器 在传输层上实现网络互连 PS 二层交换机在链路层 路由 三层交换机在网络层 集线器 中继器在物理层 是最复杂的网络互联设备 仅用于两个高层协议不同的网络互连 网关有很多种 最常用的是TCP IP协议里的网
  • DDoS攻击原理及防御

    转自 微点阅读 https www weidianyuedu com 随着网络时代的到来 网络安全变得越来越重要 在互联网的安全领域 DDoS Distributed DenialofService 攻击技术因为它的隐蔽性 高效性一直是网络
  • matlab自回归模型AIC,时间序列笔记-自回归模型(二)

    笔记说明 在datacamp网站上学习 Time Series with R track Introduction to Time Series Analysis 课程 做的对应笔记 学识有限 错误难免 还请不吝赐教 如无特殊说明 笔记中所
  • gcc常见编译参数介绍

    1 常见编译参数介绍 gcc可以说是个伟大的编译器集合 支持c c object c java fortran pascal ada等一大堆语言 同时支持几乎所有32位以上的cpu和部分16位 8位cpu 因此几乎所有开源操作系统 商业un
  • uniapp微信小程序 ios端部分机型屏幕可左右滑动原因即处理

    1 原因 因为部分元素超过了屏幕尺寸大小 2 处理 在超出屏幕尺寸的元素上一级使用 width 100 overflow x hidden 如果是图片导致的 则需要把多余的裁剪掉
  • ubuntu虚拟机搭建hadoop完全分布式集群

    一 需要的工具 需要的工具我已经完成分享 需要的可以直接在网盘中下载 VMware15 Workstation Pro 提取码 pp12 ubuntu16 18 19 镜像 提取码 yfj0 Xshell Xftp 提取码 6ao9 jdk
  • 7月网络学习报告

    原始代码 import torch import torch nn as nn import torch nn functional as F import torchvision from torchvision import datas
  • C++ 基础知识

    C 基础知识 一 语法 1 指针常量 常量指针 2 内存模型 3 引用 4 C 中面向对象的三大特性 5 纯虚函数和抽象类 6 文件操作 7 模板与泛型 8 STL 一 语法 1 指针常量 常量指针 指针常量 顾名思义 指针是一个常量 所以