C++初学(11)

news2024/11/26 5:50:56

不知不觉就第11篇了QWQ

11.1、指针和自由存储空间

之前提到了计算机程序在存储数据时必须跟踪的3个基本属性:

(1)信息存储在何处;

(2)存储的值为多少;

(3)存储的信息时什么类型。

之前我们通过定义一个简单变量,让声明语句指出了值的类型和符号名,让程序为值分配内存,还在内部跟踪该内存单元。

下面来看另一种方法:以指针为基础,指针是一个变量,其存储的是值的地址,而不是值本身。在讨论指针之前,我们只需对变量应用地址运算符(&),就可以获得它的位置。(这个学过C语言的肯定不陌生)下面给一个程序:

#include <iostream>
int main()
{
	using namespace std;
	int donuts = 6;
	double cups = 4.5;

	cout << "donuts value= " << donuts;
	cout << " and donuts address = " << &donuts << endl;

	cout << "cups value = " << cups;
	cout << " and cups address = " << &cups << endl;
	return 0;
}

显示地址时,该实现的cout使用十六进制表示法,因为这是常用于描述内存的表示法。在该实现中,donuts的存储位置比cups要低。两个地址的差为0000006FCE94F8C8-0000006FCE94F8C4=4。因为donuts的类型为int,而这种类型使用4个字节。

处理存储数据的新策略刚好相反,将地址视为指定的值,而将值视为派生量。一种特殊类型的变量——指针用于存储值的地址,因此指针名表示的是地址。*运算符被称为间接值或解除引用运算符,将其应用于指针,可以得到该地址处存储的值(这和乘法使用的符号相同;C++会根据上下文确定指的是什么)。

#include <iostream>
int main()
{
	using namespace std;
	int updates = 6;
	int* p_updates;
	p_updates = &updates;

	cout << "Values :updates= " << updates;
	cout << ", *p_updates= " << *p_updates << endl;

	cout << "Adresses:&updates= " << &updates;
	cout << ",p_updates= " << p_updates << endl;

	*p_updates += 1;
	cout << "Now updates= " << updates << endl;
	return 0;
}

int变量updates和指针变量p_updates只不过是同一枚硬币的两面。变量updates表示值,并使用&运算符来获取地址;而p_updates表示地址,并使用*运算符来获得值。由于p_updates指向updates,因此*p_updates和updates完全等价,可以使用int变量来使用。

11.1.1、声明和初始化指针

int *p_updates;

这个声明表明*p_updates的类型为int。由于*运算符被用于指针,因此p_updates变量本身必须是指针。我们可以认为p_updates指向int类型,或者该类型是指向int的指针。

一般来说,C程序员使用这种格式:

int *ptr;

这强调*ptr是一个int类型的值。而很多C++程序员使用这种格式:

int* ptr;

这强调的是:int*是一种类型——指向int的指针。

(其实在哪添加空格是自己喜好,对编译器没啥影响,甚至不加也行)

但是如果要声明多个变量,每个指针变量名都需要使用一个*。

可以在声明语句中初始化指针。被初始化的是指针而不是它指向的值。也就是说,下面的语句将pt的值设置为&higgens:

int higgens=6;
int* pt=&higgens;

11.1.2、指针的危险

在C++中创建指针时,计算机将分配用来存放地址的内存,但不会分配用来存储指针所指向数据的内存。为数据提供空间是一定要的步骤。一定要在对指针应用解除引用运算符(*)之前,将指针初始化为一个确定的、适当的地址。

11.1.3、指针和数字

指针不是整型,虽然计算机通常把地址当作整数看待,但从概念上,整数可以进行运算,而指针运算没有意义,因此不能将整数赋给指针:(那前面的地址举例)

int* pt;
*pt=0000006FCE94F8C8;

在这里,左边是指向int的指针,因此可以赋给地址。但右边是一个整数,这段语句没有告诉程序这个整数是一个地址,因此不能赋值。如果要使用,应通过强制类型转换将数字转换为适当的地址类型:

int* pt;
*pt= (int *)0000006FCE94F8C8;

这样两边都是地址,赋值才有效。

11.1.4、使用new来分配内存

前面我们将指针初始化为变量的地址;变量是在编译时分配的有名称的内存,而指针只是为可以通过名称直接访问的内存提供的一个别名。指针真正的作用时在运行阶段分配未命名的内存以存储值。在C语言中,可以用库函数malloc()来分配内存;在C++中依然可以这么做,但C++有更好的方法——new运算符

在运行阶段为一个int值分配未命名的内存,并使用指针来访问这个值,这里的关键所在是C++的new运算符。程序员要告诉new,需要为哪种数据类型分配内存;new将找到一个长度正确的内存块,并返回该内存块的地址。例子:

int* pn=new int;

new int告诉程序,需要适合存储int的内存。new运算符根据类型来确定需要多少字节的内存。然后它找到这样的内存,并返回其地址。接下来将地址赋给pn,pn是被声明为指向int的指针。现在pn是地址,而*pn是存储在那里的值。为一个数据对象(可以是结构,也可以是基本类型)获得并指定分配内存的通用格式如下:

typeName * pointer_name=new typeName;

#include <iostream>
int main()
{
	using namespace std;
	int nights = 1001;
	int* pt = new int;
	*pt = 1001;

	cout << "nights value = ";
	cout << nights << ":location = " << &nights << endl;
	cout << "int ";
	cout << "value = " << *pt << ":location = " << pt << endl;
	double* pd = new double;
	*pd = 10000001.0;

	cout << "double ";
	cout << "value= " << *pd << ":location= " << pd << endl;
	cout << "location of pointer pd: " << &pd << endl;
	cout << "size of pt = " << sizeof(pt) ;
	cout << ": size of *pt = " << sizeof(*pt) << endl;
	cout << "size of pd = " << sizeof(pd) ;
	cout << ": size of *pd = " << sizeof(*pd) << endl;
	return 0;
}

       

程序说明:该程序使用new分别为int类型和double类型的数据对象分配内存。指针pt和pd指向这两个数据对象,如果没有它们,将无法访问这些内存单元。现在就可以像使用变量那样使用*pt和*pd了。

该程序还指出了必须声明指针所指向的类型的原因之一:地址本身只指出了对象存储地址的开始,而没有指出其类型(使用的字节)。从两个值的地址可以知道,它们都只是数字,并没有提供类型或长度信息。另外指向int的指针长度和double的指针相同,因为它们都是地址。

11.1.5、使用delete释放内存

当需要内存时,可以使用new来请求,而有请求,就会有删除。delete运算符使得在使用内存后,能够将其归还给内存池,能更有效地使用内存。使用delete时,后面要加上指向内存块的指针:

int* pt=new int;
delete pt;

这将释放pt指向的内存,而不会删除指针pt本身。可以将pt重新指向另一个新分配的内存块。一定要配对地使用new和delete;否则将会发生内存泄漏。

注:只能用delete来释放使用new分配的内存,然而对空指针使用delete是安全的。一般来说不能创建两个指向同一个内存块的指针,因为这将增加错误的删除同一个内存块两次的可能性。

11.1.6、使用new来创建动态数组

11.1.6.1、使用new创建动态数组

在C++中,创建动态数组很容易,只要将数组的元素类型和元素数目告诉new即可。必须在类型名后面加上方括号,其中包含元素数目。例如:

int* psome=new int [10];

new运算符返回第一个元素的地址,这个地址被赋给指针psome。当程序使用完new分配的内存块时,应使用delete释放它们。对于使用new创建的数组,应使用另一种格式的delete来释放:

delete [] psome;

方括号告诉程序,应释放整个数组,而不仅仅是指针指向的元素。

使用new和delete时,应遵循下面的规则:

(1)不要使用delete释放不是new分配的内存。

(2)不要使用delete释放同一块内存块两次。

(3)如果使用new[ ]为数组分配内存,应使用delete[ ]来释放。

(4)对空指针应用delete是安全的。

11.1.6.2、使用动态数组

我们使用上面的声明,可以将它看作是一跟指向该元素的手指。假设int占4个字节,则将手指沿正确的方向移动4个字节,手指指向第二个元素。下面做法对学过C语言的会很熟悉:可以使用psome[0]访问第一个元素,第二个元素则可以使用psome[1],以此类推。

#include <iostream>
int main()
{
	using namespace std;
	double* p3 = new double[3];
	p3[0] = 0.2;
	p3[1] = 0.5;
	p3[2] = 0.8;
	cout << "p3[1] is " << p3[1] << ".\n";
	p3 = p3 + 1;
	cout << "Now p3[0] is " << p3[0] << " and ";
	cout << "p3[1] is " << p3[1] << ".\n";
	p3 = p3 - 1;
	delete[] p3;
	return 0;
}

p3=p3+1;

我们不能修改数组名的值。但指针是变量,因此可以修改它的值。上面这个作用是导致p3指向第二个元素而不是第一个,减去1则指向第一个值,便能给delete[ ]提供正确的地址。

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

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

相关文章

GitHub爆赞的Web安全防护指南,网络安全零基础入门必备教程!

web安全现在占据了企业信息安全的很大一部分比重&#xff0c;每个企业都有对外发布的很多业务系统&#xff0c;如何保障web业务安全也是一项信息安全的重要内容。 然而Web 安全是一个实践性很强的领域&#xff0c;需要通过大量的练习来建立对漏洞的直观认识&#xff0c;并积累…

xtrabackup搭建MySQL 8.0 主从复制

xtrabackup搭建MySQL 8.0 主从复制 安装MySQL 8.0.37安装xtrabackupGTIDs初始化从库参考&#xff1a;GTID概述GTID相较与传统复制的优势GTID自身存在哪些限制GTID工作原理简单介绍如何开启GTID复制GTID与传统模式建立复制时候语句的不同点传统复制GTID复制 GTID同步状态简单解析…

Docker技术背景与应用:解决现代开发中的关键问题

目录 Docker技术背景与应用&#xff1a;解决现代开发中的关键问题 一、Docker的技术背景 1. 什么是Docker&#xff1f; 2. Docker的核心组件 3. Docker的历史发展 二、Docker解决了哪些问题&#xff1f; 1. 环境一致性问题 2. 依赖管理问题 3. 部署复杂性问题 4. 资源…

微信小程序实现上传照片功能

案例&#xff1a; html: <view class"zhengjianCont fontSize30" style"margin-bottom: 40rpx;"><view class"kuai"><image binderror"imageOnloadError" bind:tap"upladPhoto" data-params"business…

二叉树——2.对称二叉树

力扣题目链接 给定一个二叉树&#xff0c;检查它是否是镜像对称的。 示例&#xff1a; 上述的二叉树就是对称的。 在做二叉树题目时&#xff0c;最重要的是你要找到题目中的二叉树是怎么遍历的。本题中要检查二叉树是否镜像对称&#xff0c;这就不是单独判断某个父节点的左右…

Java二十三种设计模式-策略模式(13/23)

策略模式&#xff1a;灵活算法的替换与扩展 引言 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了算法族&#xff0c;分别封装起来&#xff0c;让它们之间可以互相替换&#xff0c;此模式让算法的变化独立于使用算法的客户。 基础…

menuconfig+Kconfig的简单配置

目录 1.背景 2.管理方案 2.1&#xff1a;.h中直接定义 2.2&#xff1a;.batCmake 2.3&#xff1a;Kconfig 2.3.1 环境安装 2.3.2 代码 2.3.2.1 目录结构 2.3.2.2 ble目录下的Kconfig 2.3.2.3 hardware目录下的Kconfig 2.3.2.4 rtos目录下的Kconfig 2.3.2.5 根目录 …

【性能】console.log引起内存泄漏

如下代码中的console.log会引起内存泄漏 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Example<…

降级、熔断、限流学习笔记

1. 面对高流量出现故障的原因 由于依赖的资源或者服务不可用&#xff0c;最终导致整体服务宕机。在电商系统中就可能由于数据库访问缓慢&#xff0c;导致整体服务不可用。 乐观地预估了可能到来的流量&#xff0c;当有超过系统承载能力的流量到来时&#xff0c;系统不堪重负&a…

Vue.js 3.x 必修课|008|计算属性:提高代码服用性和可维护性

欢迎关注公众号:CodeFit。 创作不易,如果你觉得这篇文章对您有帮助,请不要忘了 点赞、分享 和 关注,为我的 持续创作 提供 动力! 欢迎订阅《Vue 3.x 必修课| 2024》:http://t.csdnimg.cn/hHRrM 精品内容,物超所值,一杯咖啡的价格(9.9 元)只为持续创作提供动力。 在 …

【AI】人工智能时代,程序员如何保持核心竞争力?

目录 程序员在AI时代的应对策略1. 引言2. AI在编程领域的影响2.1 AI辅助编程工具的现状2.2 AI对编程工作的影响2.3 程序员的机遇与挑战 3. 深耕细作&#xff1a;专注领域的深度学习3.1 专注领域的重要性3.2 深度学习的策略3.2.1 选择合适的领域3.2.2 持续学习和研究3.2.3 实践与…

【PXE+kickstart】linux网络服务之自动装机

PXE&#xff1a; 简介&#xff1a;PXE(Preboot execute environment 是一种能够让计算机通过网络启动的引导方式&#xff0c;只要网卡支持PXE协议即可使用Kickstart 是一种无人值守的安装方式&#xff0c;工作原理就是预先把原本需要运维人员手工填写的参数保存成一个 ks.cfg 文…

centos7安装 ES集群 elasticsearch

这里写自定义目录标题 编写启动脚本 elasticsearch.sh启动可能报错&#xff1a;elasticsearch 7.10启动报错 bootstrap checks failed解决方法问题原因&#xff1a;注意 退出xshell&#xff0c;重新登录&#xff1a; 上面两个配置项改完后&#xff0c;ES启动用户(es 或root) **…

Debian | 更换 Gnome 至 Xfce4

Debian | 更换 Gnome 至 Xfce4 更新源 sudo apt update && sudo apt upgrade安装 xfce4 sudo apt install xfce4我选择 lightdm&#xff0c;回车 切换桌面 sudo update-alternatives --config x-session-manager输入 xfce 所在序号&#xff0c;我这里是 3 卸载 …

洛谷 P1560 [USACO5.2]蜗牛的旅行Snail Trails(c++)

describe 蜗牛在制定今天的旅游计划&#xff0c;有 n 个景点可选&#xff0c;它已经把这些景点按照顺路游览的顺序排 成一排了&#xff0c;每个地方有相应的景观&#xff0c;这里用一个整数表示。 蜗牛希望选取连续的一段景点&#xff0c;还要选出来的每一个景点的景观都不同…

ASP.NET Core基础 - 简介

目录 一. 简介 A、跨平台性 B、高性能 C、开源性 D、模块化与可扩展性 E、集成现代前端技术 二. ASP.NET 4.x 和 ASP.NET Core 比较 A、架构与平台支持 B、性能 C、开发体验 D、社区支持与生态系统 三. NET 与 .NET Framework 比较 A、概念范围 B、跨平台能力 C…

文献综述如何有助于识别研究中的关键变量和概念

VersaBot文献综述助手 进行良好的文献综述对于从多个方面确定研究的关键变量和概念起着至关重要的作用&#xff1b; 1.揭示相关领域和理论&#xff1a; 通过沉浸在现有的学术研究中&#xff0c;你会遇到围绕你的主题的各种理论和概念。这些可以作为识别与您的研究问题相关的潜…

天和环保业绩波动性明显,应收账款逾期率和回款率欠佳

《港湾商业观察》施子夫 7月17日&#xff0c;北交所网站更新唐山天和环保科技股份有限公司&#xff08;以下简称&#xff0c;天和环保&#xff09;及保荐机构江海证券关于第三轮审核问询函的回复。 公开信息显示&#xff0c;2023年6月&#xff0c;天和环保的IPO申请获受理。今…

Linux IPC解析:匿名命名管道与共享内存

目录 一.IPC机制介绍二.匿名与命名管道1.匿名管道2.命名管道3.日志 三.共享内存三.System V 标准1.System V简介2.IPC在内核的数据结构设计3.信号量 一.IPC机制介绍 IPC&#xff08;Inter-Process Communication&#xff0c;进程间通信&#xff09;是计算机系统中不同进程之间交…

还没用过OBS Studio?快来提升你的技术分享效率!

前言 在浩瀚的数字海洋中&#xff0c;有这么一款神器&#xff0c;它低调却光芒四射&#xff0c;默默改变着无数内容创作者的命运&#xff1b;嘿&#xff0c;你猜怎么着&#xff1f;它既不是天价的专业设备&#xff0c;也不是遥不可及的神秘黑科技&#xff0c;而是开源世界的瑰宝…