C++新经典08--范围for、new内存动态分配与nullptr

news2024/11/16 22:43:47

范围for语句

C语言部分学习过了for语句,在C++11中for语句的能力被进一步扩展,引入了范围for语句,用于遍历一个序列。看看如下范例:

    int v[]{12,13,14,16,18};
    //数组ⅴ中每个元素依次放入x并打印x值。相当于把ⅴ的每个元素值复制到x中,然后打印
    for (auto x : v)
    {
        cout << x << endl;
    }

    //{}中是一个元素序列,for就是应用于任意的这种元素序列
    for(auto x : {11,34,56,21,34,34})
    {
        cout << x << endl;
    }

上面范例中第一个for语句的写法有个缺点,多了一个复制的动作,也就是把数组v中的元素值依次复制(赋值)到了x中,然后循环输出x值。那如何修改一下以避免这种复制动作,提高程序运行效率呢?非常简单,只需要把for这行代码修改成如下即可:

for (auto &x : v)		//使用引用的方式,避免数据的复制动作

一般来讲,一个容器只要其内部支持begin和end成员函数用于返回一个迭代器,能够指向容器的第一个元素和末端元素的后面,这种容器就可以支持范围for语句(容器后面讲)。

动态内存分配问题

在C++中,把内存进一步更详细地分成5个区域:
(1)栈。函数内的局部变量一般在这里创建,由编译器自动分配和释放。(2)堆。由程序员使用malloc/new申请,free/delete释放。malloc/new申请并使用完毕后要及时free/delete以节省系统资源,防止资源耗尽导致程序崩溃。如果程序员忘记free/delete,程序结束时会由操作系统回收这些内存。
(3)全局/静态存储区。全局变量和静态变量放这里,程序结束时释放。
(4)常量存储区。存放常量,不允许修改,如用双引号包含起来的字符串。(5)程序代码区。相当于C语言中的程序代码区。

这5个区域重点关注堆和栈,其他几个区域简单理解即可。堆和栈都相当于C语言部分所说的动态存储区,但用途不同。下面总结一下堆和栈的区别:
(1)栈空间有限(这是系统规定的),使用便捷。例如代码行inta=4;,系统就自动分配了一个4字节给变量a使用。分配速度快,程序员控制不了它的分配和释放。
(2)堆空间是程序员自由决定所分配的内存大小,大小理论上只要不超出实际拥有的物理内存即可,分配速度相对较慢,可以随时用new/malloc分配、free/delete释放,非常灵活。
下面介绍new/malloc与free/delete。

1.malloc和free

在C语言(不是C++)中,malloc和free是系统提供的函数,成对使用,用于从堆(堆空间)中分配和释放内存。malloc的全称是memoryallocation,翻译成中文含义是“动态内存分配”。一般形式为:
在这里插入图片描述
说明:malloc向系统申请分配指定NumBytes字节的内存空间。返回类型是void类型。void表示未确定类型的指针。C/C++规定,void*类型可以强制转换为任何其他类型的指针。如果分配成功则返回指向被分配内存的指针,如果分配失败则返回空指针NULL。分配成功后且当内存不再使用时,应使用free()函数将内存释放。

free函数的一般形式为:
在这里插入图片描述
说明:该函数是将之前用malloc分配的内存空间还给程序或者操作系统,也就是释放先前分配的内存,这样这块内存就被系统回收并在需要的时候由系统自由分配出去再使用。

看看如下范例:

    int *p = NULL;
    p = (int*)malloc(10 * sizeof(int));		//分配了40字节
    if (p != NULL)
    {
        *p=5;	//这种写法其实只会用到分配的40字节中的4字节
        cout << *p << endl;
        free(p);	//千万不要忘记,否则就是内存泄漏。如果泄漏多了,程序就会崩溃
    }

再继续看范例:

    int *p = (int*)malloc(sizeof(int)*100);	//分配可以放得下100个整数的内存空间
    if (p != NULL)
    {
        int *q = p;
        *q++=1;
        *q++=5;
        cout << *p << endl;		//1
        cout << *(p+1) << endl;		//5
        free(p);
    }

2.new和delete

new和delete是运算符,不是函数。C++中使用new和delete从堆中分配和释放内存,两者成对使用。

首先读者要理解一点,那就是new/delete做了和malloc/free同样的事情——分配和释放内存,同时,new/delete还做了更多的事情。这里先看一看,new/delete在分配内存方面的用法。new一般使用格式有如下几种:

在这里插入图片描述

看看如下范例:

    int * myint = new int;
    if (myint != NULL)	//其实如果new失败可能不会返回NULL,而是直接报异常
    {
        *myint = 8;	//myint代表指针指向的变量
        cout << *myint << endl;		//8
        delete myint;	//释放
    }

再继续看范例:

    int * myint = new int(18);		//分配内存同时将该内存空间的内容设置为18
    if (myint != NULL)	
    {
        *myint = 8;	//myint代表指针指向的变量
        cout << *myint << endl;		//8
        delete myint;	//释放
    }

再继续看范例:

int* a  = new int[100];		//开辟一个大小为100的整型数组空间
if (a != NULL)
{
	int * p =  a;
	*p++=12;
	*p++=18;
	cout << *a << endl;  		//12
	cout << *(a + 1) << endl;		//18
	//new时用了[],delete时就要用[],否则回收的内存就是第一个数组元素空间而不是整个数
	//组,[]起了回收整个数组的作用,delete中[]内不用写数组中元素个数,保持空着,系统有办
	//法知道这个数组大小,写了数字也会被系统忽略
	delete[] a;		//释放int数组空间
}

有几点说明:
(1)配对使用,有malloc成功必有free,有new成功必有delete。
(2)free/delete不要重复调用,因为free/delete的内存可能被系统立即回收后再利用,再free/delete一次很可能把不是自己的空间释放掉了,导致程序运行出现异常甚至崩溃。

nullptr

nullptr是C++11引入的新关键字,代表“空指针”。
看看如下范例:

    char* p = NULL;	//NULL实际就是0
    char* q = nullptr;	//设置断点观察发现p和q都是0x00000000,似乎都一样
    int *a = nullptr;
    if (p == nullptr)
    //条件成立
    {
        cout << "nullo" << endl;
    }

有资料指出:使用nullptr能够避免在整数和指针之间发生混淆。但笔者认为这句话说得有点模棱两可。看看下面的演示范例:

    cout << typeid(NULL).name()<< endl;	//int
    cout << typeid(nullptr).name()<< endl; //std:nullptr_t

上面范例中,typeid先不深入解释,后面章节会详细学习,这里只理解成“用于取类型”。然后.name()可以打印出类型名,通过结果可以看到,NULL和nullptr两者的类型是不同的。

在后面学习函数重载时,因为NULL和nullptr类型不同,所以如果把这两者当函数实参传递到函数中去,则会导致因为实参类型不同而调用不同的重载函数。看看如下范例:

在这里插入图片描述
给出一些结论:(1)对于指针的初始化,能用nullptr的全部用nullptr。(2)以往用到的与指针有关的NULL的场合,能用nullptr取代的全部用nullptr取代。

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

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

相关文章

第11步---MySQL的优化

第11步---MySQL的优化 1.概念 原先写功能。后来对平静进行优化 设计 查询语句 索引 存储 2.查看执行效率 -- 查看当前会话sql得执行类型得统计信息SHOW session STATUS like Com%上面展示得信息就是统计了当前会话得执行得操作得次数。 -- 查看全局得 SHOW GLOBAL STATU…

【C++入门到精通】C++入门 —— deque(STL)

阅读导航 前言一、deque简介1. 概念2. 特点 二、deque使用1. 基本操作&#xff08;增、删、查、改&#xff09;2. 底层结构 三、deque的缺陷四、 为什么选择deque作为stack和queue的底层默认容器总结温馨提示 前言 文章绑定了VS平台下std::deque的源码&#xff0c;大家可以下载…

SOLIDWORKS中一些不常用却很实用的功能介绍

1.过滤 FeatureManager 设计树 我们可以在FeatureManager 设计树过滤器中搜索特定的零件特征和装配体零部件。 2.添加文件夹和子文件夹 在零件或装配体文件中&#xff0c;您可添加文件夹到 FeatureManager 设计树内。 您可重新命名新的文件夹并将额外项目拖动到新的文件夹中。…

(一)Dubbo源码解析:增强SPI

〇、前言 在Dubbo的架构设计中&#xff0c;如何可以通过“类插拔”的方式&#xff0c;对其功能进行灵活的扩展或者削弱&#xff0c;那么&#xff0c;SPI起到了极其关键的作用。本篇文章作为分析Dubbo源码的第一篇文章&#xff0c;我们先暂时放下“服务注册发布流程”、“服务启…

Linux:shell脚本:基础使用(6)《正则表达式-awk工具》

简介 awk是行处理器: 相比较屏幕处理的优点&#xff0c;在处理庞大文件时不会出现内存溢出或是处理缓慢的问题&#xff0c;通常用来格式化文本信息 awk处理过程: 依次对每一行进行处理&#xff0c;然后输出 1&#xff09;awk命令会逐行读取文件的内容进行处理 2&#xff09;a…

攻防世界-disabled_button

原题解题思路 看页面源码 把这个删了就行

ESP32-C3 手动启用 Secure Boot V2 与 Flash 加密流程

ESP-IDF 中 flash 加密可以在 bootloader 阶段自动启用&#xff0c;但是这需要设备自加密后重启一次&#xff0c;为了节省这次重启的步骤&#xff0c;你可以选择通过一些脚本工具在外部启用 flash 加密。 本篇文档用于介绍 ESP32-C3 手动启用 Secure Boot V2 与 Flash 加密的操…

矩阵乘法(C++ mpi 并行实现)

矩阵乘法有2种思路&#xff0c;我最先想到的是第一种思路&#xff0c;但是时间、空间复杂度都比较高。后面参考了一些资料&#xff0c;实现了第二种思路。 一、思路1&#xff1a;按行、列分块 矩阵乘法有一个很好的性质&#xff0c;就是结果矩阵的每个元素是不互相依赖的&…

如何批量加密PDF文件并设置不同密码 - 批量PDF加密工具使用教程

如果你正在寻找一种方法来批量加密和保护你的PDF文件&#xff0c;批量PDF加密工具是一个不错的选择。 它是一个体积小巧但功能强大的Windows工具软件&#xff0c;能够批量给多个PDF文件加密和限制&#xff0c;包括设置打印限制、禁止文字复制&#xff0c;并增加独立的打开密码。…

React实战 - React路由鉴权

目录 一、React-Router知识回顾 二、路由鉴权应用分析 三、路由鉴权配置 四、权限控制 一、React-Router知识回顾 React-router相关的文章中我已经给大家演示了最基础的应用&#xff1a; <Switch ><Route path"/products/:id" component{ProductDetai…

【Rust】Rust学习 第十七章Rust 的面向对象特性

面向对象编程&#xff08;Object-Oriented Programming&#xff0c;OOP&#xff09;是一种模式化编程方式。对象&#xff08;Object&#xff09;来源于 20 世纪 60 年代的 Simula 编程语言。这些对象影响了 Alan Kay 的编程架构中对象之间的消息传递。他在 1967 年创造了 面向对…

Blob,File文件上传下载的内容笔记

Blob 对象表示一个不可变、原始数据的类文件对象&#xff0c;可以看做是存放二进制数据的容器 。 简单来说Blob就是一个二进制的对象&#xff0c;我们可以通过这个blob对象直接读取文件内容 Blob和Flie没什么区别&#xff0c;File继承于Blob,就是多了一个name属性&#xff0c;表…

当今职场,正在加速淘汰 “巨婴员工”

我担任过多家上市公司的技术高管职位&#xff0c;在工作中经常会遇到巨婴型员工&#xff0c;他们外在的表现是&#xff0c;不能够很好地管理自己&#xff0c;缺乏自律&#xff0c;缺乏起码的抗挫折能力和抗压能力&#xff0c;需要领导呵护着、同事们忍让着。作为一名管理者&…

科技成果鉴定测试有什么意义?专业CMA、CNAS软件测评公司

科技成果鉴定测试是指通过一系列科学的实验和检测手段&#xff0c;对科技成果进行客观评价和鉴定的过程。通过测试&#xff0c;可以对科技成果的技术优劣进行评估&#xff0c;从而为科技创新提供参考和指导。 一、科技成果鉴定测试的意义 1、帮助客户了解科技产品的性能特点和…

排序(七种排序)

1.插入排序 2.希尔排序 3.选择排序 4.堆排序 5.冒泡排序 6.快速排序 7.归并排序 1.插入排序 1.1思路 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为 止&#xff0c;得到一个新的有序序列 1.2实现 //插入排…

[计算机入门] 个性化设置系统

3.2 个性化设置系统 在Windows系统中&#xff0c;个性化设置可以让用户根据自己的喜好和需求对系统进行定制和调整&#xff0c;包括桌面背景、声音、屏幕保护程序、鼠标指针、字体等。通过个性化设置&#xff0c;用户可以创建自己的独特界面和用户体验&#xff0c;使系统更加符…

HBuilderX获取iOS证书的打包步骤

简介&#xff1a; 目前app开发&#xff0c;很多企业都用H5框架来开发&#xff0c;而uniapp又是这些h5框架里面最成熟的&#xff0c;因此hbuilderx就成为了开发者的首选。然而,打包APP是需要证书的&#xff0c;那么这个证书又是如何获得呢&#xff1f; 生成苹果证书相对复杂一些…

Hyper-V Linux服务器安装

官方文档&#xff1a;在 Windows 10 创意者更新上使用 Hyper-V 创建虚拟机 | Microsoft Learn 1 新增虚拟交换机 打开Hyper-V管理器&#xff0c;找到右侧的操作列&#xff0c;点击“虚拟交换机管理器”&#xff1a; 点击“新建虚拟网络交换机”&#xff0c;交换机类型选择“外部…

用idea解决代码合并冲突

参考文章&#xff1a; IDEA&#xff1a;idea中的Git冲突解决&#xff08;非常重要&#xff09; idea操作git时 合并分支解决冲突 一、前言 1.什么事冲突&#xff1f; 冲突是指当你在提交或者更新代码时被合并的文件与当前文件不一致。读起来有点绕&#xff0c;结合下面的案例…

16、Flink 的table api与sql之连接外部系统: 读写外部系统的连接器和格式以及FileSystem示例(1)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…