C++核心编程——内存分区、引用、函数提高和函数重载

本专栏记录C++学习过程包括C++基础以及数据结构和算法,其中第一部分计划时间一个月,主要跟着黑马视频教程,学习路线如下,不定时更新,欢迎关注
当前章节处于:
---------第1阶段-C++基础入门
---------第2阶段实战-通讯录管理系统,
====>第3阶段-C++核心编程
---------第4阶段实战-基于多态的企业职工系统
---------第5阶段-C++提高编程
---------第6阶段实战-基于STL泛化编程的演讲比赛
---------第7阶段-C++实战项目机房预约管理系统

文章目录

  • 一、 内存分区
    • 1.1 代码区
    • 1.2 全局区
    • 1.3 栈区
    • 1.4 堆区
  • 二. 引用
    • 2.1 引用的基本使用
    • 2.2 引用做函数参数
    • 2.3 引用做函数返回值
    • 2.4 引用的本质
    • 2.5 常量引用
  • 三. 函数提高
    • 3.1 函数的默认参数
    • 3.2 占位参数
  • 四. 函数重载

一、 内存分区

C++程序在执行时,内存大致方向分为4个区域,不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程。代码区和全局区是在程序运行前,栈区和堆区是在代码运行后

  • 代码区:存放函数体的二进制码,有操作系统进行管理
  • 全局区:存放全局变量和静态变量以及常量
  • 栈区:由编译器自动分配释放,存放函数的函数值,局部变量等。
  • 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收

1.1 代码区

存放CPU执行的机器指令

  • 代码区是共享的,只需要在内存中有一份代码即可
  • 代码区是只读的,防止程序意外地修改了它的指令

1.2 全局区

全局变量和静态变量存放在此。
全局区还包括了常量区,字符串常量和其他常量也存放在这里。
该区域的数据在程序结束后由操作系统释放。

#include <iostream>
using namespace std;
// 全局变量 ----- 全局区
int g_a = 0;
int g_b = 0;
// 全局常量 ----- 全局区
const int c_g_a = 0;
const int c_g_b = 0;
int main() {// 以下为全局区// 全局变量cout << "全局变量a的地址为" << (int)&g_a << endl;cout << "全局变量b的地址为" << (int)&g_b << endl;// 全局常量cout << "全局常量a的地址为" << (int)&c_g_a << endl;cout << "全局常量b的地址为" << (int)&c_g_b << endl;// 静态变量static int s_a = 0; // static修饰的是静态变量static int s_b = 0;cout << "静态变量a的地址为" << (int)&s_a << endl;cout << "静态变量b的地址为" << (int)&s_b << endl;// 字符串常量cout << "字符串常量a的地址为" << (int)&"Hallo world" << endl;// 以下为非全局区// 局部变量int l_a = 0;int l_b = 0;cout << "局部变量a的地址为" << (int)&l_a << endl;cout << "局部变量b的地址为" << (int)&l_b << endl;// 局部常量// const修饰的常量const int c_l_a = 0;const int c_l_b = 0;cout << "局部常量a的地址为" << (int)&l_a << endl;cout << "局部常量b的地址为" << (int)&l_b << endl;system("pause");return 0;}
全局变量a的地址为1109844336
全局变量b的地址为1109844340
全局常量a的地址为1109830576
全局常量b的地址为1109830580
静态变量a的地址为1109844344
静态变量b的地址为1109844348
字符串常量a的地址为1109831072
局部变量a的地址为1807742644
局部变量b的地址为1807742676
局部常量a的地址为1807742644
局部常量b的地址为1807742676
请按任意键继续. . .

可以看到全局变量,全局常量,静态变量,字符串常量是存储在全局区,其他量存储在非全局区。

1.3 栈区

  • 由编译器自动分配释放,存放函数的参数值,局部变量等。
  • 不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

1.4 堆区

程序员分配释放,若程序员不释放,程序结束由操作系统回收
在C++中主要利用new在堆区开辟内存。

#include <iostream>
using namespace std;int* func() {int* p = new int(10);  // new关键字在堆区域开辟地址return p;
}
int main() {cout << *func() << endl;cout << *func() << endl;cout << *func() << endl;system("pause");return 0;}
10
10
10
请按任意键继续. . .

new操作符
利用new操作符开辟数据
堆区开辟的数据,有程序员手动开辟,手动释放,释放使用delete
利用new创建的数据,会返回该数据对应的类型的指针

#include <iostream>
using namespace std;int* func() {int* p = new int(10);  // new关键字在堆区域开辟地址return p;
}
int main() {cout << *func() << endl;int* p = func();cout << *p << endl;// 删除操作delete p;// cout << *p << endl; 会报错,原因是p已经从堆区域删除system("pause");return 0;}

new在堆区开辟一个数组

#include <iostream>
using namespace std;
int* test() {int *arr = new int[10]; // new创建数组for (int i = 0; i < 10; i++) {arr[i] = i; // 赋值 }for (int i = 0; i < 10; i++){cout << arr[i] << endl;}return arr;
}int main() {int *arr = test();delete[] arr; // 删除数组时要加上[]表示删除的是一个数组system("pause");return 0;}
0
1
2
3
4
5
6
7
8
9
请按任意键继续. . .

二. 引用

2.1 引用的基本使用

作用是给变量起别名,语法: 数据类型 &别名=原名

#include <iostream>
using namespace std;int main() {int a = 0;// 引用int& b = a;cout << "a=" << a<<endl;cout << "b=" << b<<endl;int* p = &a;cout << "p的值为:" << *p << endl;b = 10; // 同样也会修改a的值cout << "p的值为:" << *p << endl;cout << "a的值为:" << a << endl;cout << "a的地址为:" << (int)&a << endl;cout << "b的地址为:" << (int)&b << endl;system("pause");return 0;}
a=0
b=0
p的值为:0
p的值为:10
a的值为:10
a的地址为:-289408796
b的地址为:-289408796
请按任意键继续. . .

注意事项

  • 引用必须初始化
  • 引用在创建之后就不可改变了
int &a; // 错误 未初始化!int a = 0;
int c = 0;
// 引用
int& b = a;
int& b = c; // 报错,创建之后就不可以更改

2.2 引用做函数参数

函数传参时,可以利用引用的技术让形参修饰实参,简化指针修饰实参

#include <iostream>
using namespace std;
void swap(int &a,int&b) {int temp = a;a = b;b = temp;
}int main() {int a = 10;int b = 20;cout << "交换前a=" << a << endl;cout << "交换前b=" << b << endl;swap(a, b);cout << "交换后a=" << a << endl;cout << "交换后b=" << b << endl;system("pause");return 0;}
交换前a=10
交换前b=20
交换后a=20
交换后b=10
请按任意键继续. . .

引用传递和地址传递效果一样,都可以对实参进行修改。

2.3 引用做函数返回值

#include <iostream>
using namespace std;
// 不要返回局部变量的引用
//int &test() {
//	int a = 10;
//	cout <<"a的地址:"<< (int)& a << endl;
//	return a;
//}int &test() {static int a = 10; // 静态变量  在全局区cout <<"a的地址:"<< (int)& a << endl;return a;
}
// 引用的格式
// int & a = b;
int main() {int& ref = test();cout << "ref的地址" << (int) & ref << endl;cout << "ref的地址为:" << ref << endl;system("pause");return 0;}
a的地址:1526331140
ref的地址1526331140
ref的地址为:-858993460
请按任意键继续. . .

函数的调用可以作为左值

#include <iostream>
using namespace std;
int& test() {static int a = 10;// 静态变量return a;
}int main() {int& b = test();cout << "b的值为:" << b<<endl;test() = 1000;  // 函数调用作为左值cout << "b的值为:" << b<<endl;system("pause");return 0;}
b的值为:10
b的值为:1000
请按任意键继续. . .

2.4 引用的本质

引用的本质是在C++内部实现一个指针常量,由编译器内部完成
指针常量是指针的指向不可改变,但指针指向的值可以改变

#include <iostream>
using namespace std;
void test(int& x) {cout << x << endl;
}int main() {int a = 0;int &b = a;  // 相当于指针常量 int const *b  = &a;  指向对象不能变,指向对象的值能变b = 10; // 相当于*b =10  解引用cout << "a的值为:" << a << endl;cout << "b的值为:" << b << endl;system("pause");return 0;}
a的值为:10
b的值为:10
请按任意键继续. . .

2.5 常量引用

主要用来修饰形参,防止误操作,使用const修饰形参,防止形参修改实参

#include <iostream>
using namespace std;
void printValue(const int& a) {//a = 100; const修饰后不可再函数内部进行更改,防止误操作cout << a << endl;
}int main() {int a = 10;printValue(a);system("pause");return 0;}
10
请按任意键继续. . .

在写函数内部具体代码时,应该先判断是否需要使用const修饰,防止后续代码有误操作。

三. 函数提高

3.1 函数的默认参数

默认参数可以不传值,也可以重新传值进行覆盖。
注意事项:

  • 如果某个位置有默认参数,那么从这个默认参数后都应该有默认参数
  • 如果函数申明有默认参数,那么函数实现就不能有默认参数,两者只能有其一,防止重定义
#include <iostream>
using namespace std;
// 设置函数默认参数
int func(int a, int b = 20, int c = 30) {return a + b + c;
}
// 注意事项
// 1. 如果某个位置有默认参数,那么从这个默认参数后都应该有默认参数
// int a, int b = 20, int c; 错误// 2.如果函数申明有默认参数,那么函数实现就不能有默认参数,两者只能有其一,防止重定义
//int func2(int a = 10, int b = 10);
//int func2(int a = 20, int b = 30) {
//	return a + b;
//}int main() {cout << func(10,30) << endl;system("pause");return 0;}
70
请按任意键继续. . .

3.2 占位参数

用于占位,调用函数时必须填补该位置,也可以设置默认参数,意义不大,但后续会用到。
语法: 返回值类型 函数名 (数据类型) {}

#include <iostream>
using namespace std;
void func(int a, int) {cout << a << endl;
}int main() {func(1, 2);system("pause");return 0;}
1
请按任意键继续. . .

四. 函数重载

作用:函数名可以相同,提高复用性
需要满足如下条件:

  1. 同一个作用域
  2. 函数名称相同
  3. 函数参数类型不同或者 个数不同 或者顺序不同
    函数的返回值不可作为函数重载的条件
#include <iostream>
using namespace std;void func() {cout << "hallo world" << endl;
}
void func(int a) {cout << "hallo world" << endl;
}
int main() {func();system("pause");return 0;}

抓住重载条件即可,函数参数类型不同或者 个数不同 或者顺序不同
引用作为函数重载条件

#include <iostream>
using namespace std;
void test1(int& a) {  // int&a =10 不合法cout << "调用的test1 int& a!" << endl;
}
void test1(const int& a) {// const int&a =10 不合法cout << "调用的test1! const int& a" << endl;
}int main() {int a = 10;test1(a);test1(10);system("pause");return 0;}
调用的test1 int& a!
调用的test1! const int& a
请按任意键继续. . .

函数重载遇到默认参数情况

#include <iostream>
using namespace std;void test1(int a,int b=10) {cout << "调用int a,int b=10" << endl;
}
void test1(int a) {cout << "调用int a" << endl;
}
int main() {// test1(10); // 报错test1(10,20); // 不报错system("pause");return 0;}
调用int a,int b=10
请按任意键继续. . .

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

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

相关文章

数仓建设学习路线(一)

前言 数仓建设实践路线是语兴发布在B站的系列课程&#xff0c;搜索语兴呀即可学习完整的数仓建设理论。 大数据相关岗位 大数据常见的岗位主要包括实时开发、数据治理、数据安全、数据资产等。 其中&#xff1a; 实时开发组的主要任务是实时可视化制作(大屏/彩蛋/战报&…

前端结合MQTT实现连接 订阅发送信息等操作 VUE3

MQTT客户端下载 使用测试 在我之前文章中 MQTT下载基础使用 下面记录一下前端使用的话的操作 1.安装 npm i mqtt引入 import * as mqtt from "mqtt/dist/mqtt.min"; //VUE3 import mqtt from mqtt //VUE2 一、MQTT协议中的方法 Connect。等待与服务器建立连接…

Scanner:键盘输入功能的实现、Java程序获取一个随机数

目录 一、 Scanner&#xff1a;键盘输入功能的实现 二、Java程序获取一个随机数 一、 Scanner&#xff1a;键盘输入功能的实现 如何从键盘获取不同类型&#xff08;基本数据类型、String类型&#xff09;的变量&#xff1a;使用Scanner类 键盘输入代码的四个步骤&#xff1a…

uView Gap 间隔槽

该组件一般用于内容块之间的用一个灰色块隔开的场景&#xff0c;方便用户风格统一&#xff0c;减少工作量 #平台差异说明 App&#xff08;vue&#xff09;App&#xff08;nvue&#xff09;H5小程序√√√√ #基本使用 直接引入即可使用 通过height配置高度&#xff0c;单位…

fmt中uint128_fallback的实现分析

数据结构 class uint128_fallback {private:uint64_t lo_, hi_;public:constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {}constexpr uint128_fallback(uint64_t value 0) : lo_(value), hi_(0) {}constexpr uint64_t high() const noexcept { ret…

[VUE]2-vue的基本使用

目录 vue基本使用方式 1、vue 组件 2、文本插值 3、属性绑定 4、事件绑定 5、双向绑定 6、条件渲染 7、axios 8、⭐跨域问题 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;专注于Java领域学习&#xff0c;擅…

气膜建筑:舒适、智能、可持续

气膜建筑之所以能够拥有广阔的发展空间&#xff0c;源于其融合了诸多优势特点&#xff0c;使其成为未来建筑领域的前沿趋势。 气膜建筑注重环境可持续性和能源效率。在材料和设计上&#xff0c;它采用可回收材料、提高热保温效果&#xff0c;并积极利用太阳能等可再生能源&…

【洛谷学习自留】p9226 糖果

解题思路&#xff1a; 简单的计算题&#xff0c;用n对k取余&#xff0c;如果余数为0&#xff0c;则输出k的值&#xff0c;否则输出&#xff08;k-余数&#xff09;的值。 代码实现&#xff1a; import java.util.Scanner;public class p9226 {public static void main(Strin…

Go、Docker、云原生学习笔记全攻略:从零开始,一步步走向精通!(2024版)

第一章、Go语言学习宝典 一、介绍 01.Go 语言的前生今世 二、开发环境搭建 01.Go 语言开发环境搭建 三、初识GO语言 01.Go 多版本管理工具 02.第一个 Go 程序“hello&#xff0c;world“ 与 main 函数 03.Go 常用命令介绍 04.Go 项目代码布局 05.探索 GO 项目依赖包管…

【2023 CCF 大数据与计算智能大赛】基于TPU平台实现超分辨率重建模型部署 基于QuickRNet的TPU超分模型部署

2023 CCF 大数据与计算智能大赛 《赛题名称》 基于QuickRNet的TPU超分模型部署 巴黎欧莱雅 林松 智能应用业务部算法工程师 中信科移动 中国-北京 gpu163.com 团队简介 巴黎欧莱雅团队包含一个队长和零个队员。 队长林松&#xff0c;研究生学历&#xff0c;2019-202…

【一份老网工珍藏多年的网络配置笔记,很重要!】

01、交换机、路由器的几种配置模式及模式转换 1. 用户模式 登录到交换机&#xff08;路由器&#xff09;时会自动进入用户模式&#xff0c;提示符为 switchname>。在该模式下只能够查看相关信息&#xff0c; 对 IOS的运行不产生任何影响。 2. 特权模式 用户模式下&#xff…

精进单元测试技能 —— Pytest断言的艺术!

本篇文章主要是阐述Pytest在断言方面的应用。让大家能够了解和掌握Pytest针对断言设计了多种功能以适应在不同测试场景上使用。 了解断言的基础 在Pytest中&#xff0c;断言是通过 assert 语句来实现的。简单的断言通常用于验证预期值和实际值是否相等&#xff0c;例如&#…

蒙牛×每日互动合作获评中国信通院2023“数据+”行业应用优秀案例

当前在数字营销领域&#xff0c;品牌广告主越来越追求品效协同。针对品牌主更注重营销转化的切实需求&#xff0c;数据智能上市企业每日互动&#xff08;股票代码&#xff1a;300766&#xff09;发挥自身数据和技术能力优势&#xff0c;为垂直行业的品牌客户提供专业的数字化营…

实时云渲染的技术原理是什么?一篇文章讲透云渲染

实时云渲染依赖互联网的连接和高性能服务集群&#xff0c;为客户实时提供渲染画面&#xff0c;它有以下几个关键技术&#xff1a; 1、GPU上云 利用云服务器强大的GPU替代本地GPU进行图形处理&#xff0c;提高性能、可替换性和扩展性。2、视频流化技术 这项技术能在远程执行用户…

【ArcGIS微课1000例】0087:经纬度格式转换(度分秒转度、度转度分秒)

ArcGIS软件可以很方便的直接实现度分秒转度、度转度分秒。 文章目录 一、转换预览二、工具介绍三、案例解析一、转换预览 借助ArcGIS快速实现度分秒与度及其他格式的坐标转换。例如:度分秒→度 度分秒: 度: 二、工具介绍 转换坐标记法:将一个或两个字段包含的坐标记法从一…

ElasticSearch删除索引的命令

ElasticSearch删除索引的命令 当前命令操作是在Kibana中操作 删除单个索引 DELETE 索引名称 DELETE test删除多个索引 DELETE 索引名称1,索引名称2 DELETE test1,test2删除全部索引 DELETE /_allDELETE /*删除索引的中的全部数据 POST test/_delete_by_query {&qu…

XREAL推出其新款AR眼镜:XREAL Air 2 Ultra,体量轻内置音效

这款眼镜堪称科技的杰作&#xff0c;它以钛合金为框架&#xff0c;尽显轻盈与精致。配备的双3D环境传感器&#xff0c;宛如双眼般敏锐&#xff0c;能精准捕捉头部运动&#xff0c;让你在虚拟与现实间自由穿梭。120Hz的超高刷新率与500尼特的亮度&#xff0c;让你在4米之外感受1…

搭建React开发环境-webpack实现

周末在家学会React前端知识&#xff0c;记录下来&#xff0c;方便备查。 webpack版本&#xff1a;webpack5 编译器&#xff1a;vscode 第一步、新建项目及初始化 1&#xff09;新建项目文件夹 可命名为 my_webpack 2&#xff09;初始化项目 使用命令 npm init -y&#xff0c;…

Centos7 MongoDB安装

基础配置&#xff08;Centos7.5镜像&#xff0c;2核2GB内存&#xff0c;50GB硬盘&#xff09; 主机名IPmongodb192.168.100.124 &#xff08;在MongoDB官网有linux安装MongoDB的步骤&#xff09; &#xff08;1&#xff09;配置yum源 [rootmongodb ~]# cat /etc/yum.repos.d…

Go语言学习之旅-开篇

Go语言学习之旅-开篇 前言 最近对Go语言非常感兴趣&#xff0c;准备花一段时间来学习&#xff0c;此系列文章用于学习笔记整理与学习记录。 简介 Go&#xff08;又称 Golang&#xff09;是 Google的 Robert Griesemer&#xff0c;Rob Pike 及 Ken Thompson 开发的一种静态强…