C++语法复习笔记-1. c++指针

news2024/11/17 10:48:38

文章目录

  • 1. 计算机内存
    • 1. 储存层次
    • 2. 内存单元与地址
    • 3. 指针定义
  • 2. 左值与右值
    • 1. 数组与指针
    • 1. 概念
  • 3. C++中的原始指针
    • 1. 数组指针与指针数组
    • 2. const pointer 与 pointer to const
    • 3. 指向指针的指针
    • 4.关于野指针
      • 4.1 指向指针的指针
      • 4.2 NULL指针
      • 4.3 野指针
    • 5. 指针的基本运算
      • 5.1 & 操作
      • 5.2 *操作
      • 5.3 ++和--操作
      • 5.4 ++++与----运算符
    • 6. 内存分配
      • 6.1 总览
      • 6.2 heap堆
      • 6.3 分配和回收动态内存的原则
      • 6.4 资源管理方案--RAII
      • 6.5 c++中几种变量的对比
      • 6.6 内存泄漏问题
  • 4 更安全方式使用指针
    • 1. 智能指针
      • auto_ptr
      • unique_ptr
      • shared_ptr
      • weak_ptr
    • 2. 引用
      • 为何使用引用
      • 引用的使用
      • 函数传递总结

慕课网C++课程

1. 计算机内存

1. 储存层次

在这里插入图片描述

2. 内存单元与地址

在这里插入图片描述
在这里插入图片描述

3. 指针定义

在这里插入图片描述
在这里插入图片描述

2. 左值与右值

1. 数组与指针

在这里插入图片描述

1. 概念

在这里插入图片描述

3. C++中的原始指针

1. 数组指针与指针数组

在这里插入图片描述
在这里插入图片描述

2. const pointer 与 pointer to const

在这里插入图片描述

  • 测试

在这里插入图片描述

  • 数组只是指向了一块字符空间,没有自己真实的地址
    在这里插入图片描述
  • pStr1指向了数组指向的字符的地址,编译器做了优化

在这里插入图片描述

  • pStr2-指针变量本身的地址,为字符数组地址
    在这里插入图片描述
  • pStr3地址指向的字符串内容不能有任何改变
    在这里插入图片描述
  • pStr2指针的内容可以改变,但是与pStr1指针指向的内存一致,因此,虽然pStr1只读,但pStr2改变后,pStr1指向内容还是发生了改变
    在这里插入图片描述

3. 指向指针的指针

在这里插入图片描述

4.关于野指针

4.1 指向指针的指针

在这里插入图片描述
在这里插入图片描述

4.2 NULL指针

在这里插入图片描述
在这里插入图片描述

4.3 野指针

在这里插入图片描述

5. 指针的基本运算

5.1 & 操作

  • 取地址的值,只能做右值,取到地址后,作为一个空间变量,可以赋给一个指针,
  • 但是取特定空间的地址操作不能做左值,即,不能通过取地址操作改变地址
    在这里插入图片描述

5.2 *操作

  • 右值,是取指针指向地址空间上的对象值
  • 左值,是取指针指向的地址空间,可以对地址进行操作
    在这里插入图片描述
    在这里插入图片描述

5.3 ++和–操作

在这里插入图片描述
在这里插入图片描述

  • 不能作为左值,只是一个中间的副本,没有明确的地址
    在这里插入图片描述
    在这里插入图片描述

5.4 ++++与----运算符

在这里插入图片描述

6. 内存分配

6.1 总览

在这里插入图片描述
在这里插入图片描述

6.2 heap堆

在这里插入图片描述

6.3 分配和回收动态内存的原则

在这里插入图片描述

6.4 资源管理方案–RAII

在这里插入图片描述

6.5 c++中几种变量的对比

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.6 内存泄漏问题

在这里插入图片描述

4 更安全方式使用指针

在这里插入图片描述
在这里插入图片描述

1. 智能指针

auto_ptr

在这里插入图片描述

  • new的对象出了作用域,会自动删除
  • 指针设置为空,用nullptr,NULL是c语言语法,有二意,建议用nullptr对指针设空
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

unique_ptr

在这里插入图片描述

#include "stdafx.h"

#include <memory>   // 智能指针
#include <iostream>
using namespace std;
int main()
{
	// 在这个范围之外,unique_ptr被释放
	{
		auto i = unique_ptr<int>(new int(10));
		cout << *i << endl;
	}

	// unique_ptr
	auto w = std::make_unique<int>(10);
	cout << *(w.get()) << endl;      // 10
	//auto w2 = w; // 编译错误如果想要把 w 复制给 w2, 是不可以的。
	//  因为复制从语义上来说,两个对象将共享同一块内存。

	// unique_ptr 只支持移动语义, 即如下
	auto w2 = std::move(w); // w2 获得内存所有权,w 此时等于 nullptr
	cout << ((w.get() != nullptr) ? (*w.get()) : -1) << endl;       // -1
	cout << ((w2.get() != nullptr) ? (*w2.get()) : -1) << endl;   // 10
    return 0;
}

在这里插入图片描述

shared_ptr

  • 需要一个引用计数的信号量控制

在这里插入图片描述
在这里插入图片描述

weak_ptr

  • 解决循环引用的问题
    在这里插入图片描述
  • 用法示例
  • shared_ptr 内部是利用引用计数来实现内存的自动管理,
  • 每当复制一个 shared_ptr,引用计数会 + 1。当一个 shared_ptr 离开作用域时,引用计数会 - 1。
  • 当引用计数为 0 的时候,则 delete 内存。
// shared_ptr 
	{
		//shared_ptr 代表的是共享所有权,即多个 shared_ptr 可以共享同一块内存。
		auto wA = shared_ptr<int>(new int(20));
		{
			auto wA2 = wA;
			cout << ((wA2.get() != nullptr) ? (*wA2.get()) : -1) << endl;    // 20
			cout << ((wA.get() != nullptr) ? (*wA.get()) : -1) << endl;      // 20
			cout << wA2.use_count() << endl; // 引用计数 :2
			cout << wA.use_count() << endl;                                  // 2
		} // WA2出了作用域,消亡
		//cout << wA2.use_count() << endl;                                               
		cout << wA.use_count() << endl;                                      // 1
		cout << ((wA.get() != nullptr) ? (*wA.get()) : -1) << endl;          // 20
	}
  • move语法的使用
// move 语法
	//将 wAA 对象 move 给 wAA2,意味着 wAA 放弃了对内存的所有权和管理,此时 wAA对象等于 nullptr。
	//而 wAA2 获得了对象所有权,但因为此时 wAA 已不再持有对象,因此 wAA2 的引用计数为 1。
	auto wAA = std::make_shared<int>(30);
	auto wAA2 = std::move(wAA); // 此时 wAA 等于 nullptr,wAA2.use_count() 等于 1
	cout << ((wAA.get() != nullptr) ? (*wAA.get()) : -1) << endl;        // -1
	cout << ((wAA2.get() != nullptr) ? (*wAA2.get()) : -1) << endl;      // 30
	cout << wAA.use_count() << endl;                                     // 0
	cout << wAA2.use_count() << endl;   
  • 循环引用问题
// demo5-11.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <string>
#include <iostream>
#include <memory>
using namespace std;

// 具有shared_ptr指针的两个结构体
struct B;
struct A {
	shared_ptr<B> pb;
	~A()
	{
		cout << "~A()" << endl;
	}
};
struct B {
	shared_ptr<A> pa;
	~B()
	{
		cout << "~B()" << endl;
	}
};

// 具有shared_ptr和weak_ptr指针的两个结构体
struct BW;
struct AW
{
	shared_ptr<BW> pb;
	~AW()
	{
		cout << "~AW()" << endl;
	}
};
struct BW
{
	weak_ptr<AW> pa;
	~BW()
	{
		cout << "~BW()" << endl;
	}
};


// pa 和 pb 存在着循环引用,根据 shared_ptr 引用计数的原理,pa 和 pb 都无法被正常的释放。
// weak_ptr 是为了解决 shared_ptr 双向引用的问题。
void Test()
{
	cout << "Test shared_ptr and shared_ptr:  " << endl;
	shared_ptr<A> tA(new A());       // 1
	shared_ptr<B> tB(new B());       // 1
	cout << tA.use_count() << endl;
	cout << tB.use_count() << endl;
	tA->pb = tB;
	tB->pa = tA;
	cout << tA.use_count() << endl;  // 2
	cout << tB.use_count() << endl;  // 2
}
void Test2()
{
	cout << "Test weak_ptr and shared_ptr:  " << endl;
	shared_ptr<AW> tA(new AW());
	shared_ptr<BW> tB(new BW());
	cout << tA.use_count() << endl;   // 1
	cout << tB.use_count() << endl;   // 1
	tA->pb = tB;
	tB->pa = tA;
	cout << tA.use_count() << endl;   // 1,weak_ptr指向tA,不会对tA的引用计数产生影响
	cout << tB.use_count() << endl;   // 2
} // 当作用域结束后,Aw计数只有1,减一为0后,会正常释放,Aw消亡后,对BW的影响也消除

int main()
{
	Test();
	Test2();

    return 0;
}


在这里插入图片描述

2. 引用

为何使用引用

在这里插入图片描述
在这里插入图片描述

引用的使用

在这里插入图片描述

  • 测试
// demo5-12.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <iostream>
#include <assert.h>
using namespace std;

// 编写一个函数,输入两个int型变量a,b
// 实现在函数内部将a,b的值进行交换。
void swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
void swap2(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

int main()
{
	// 交换变量的测试
	int a = 3, b = 4;
	swap(a, b);
	assert(a == 4 && b == 3);

	a = 3, b = 4;
	swap2(&a, &b); // 用指针变量,需要传地址
	assert(a == 4 && b == 3);


    return 0;
}


函数传递总结

在这里插入图片描述

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

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

相关文章

Linux基础 IO

目录 一、文件操作 1.1 C语言文件操作 1.2 文件 系统调用接口 1.2.1 open/close函数 1.2.2 write/read函数 二、进程与文件 2.1 0&1&2 文件描述符 2.2 C语言FILE 2.3 (OS管理&进程找到) 被打开文件方法 2.3.1 struct file 描述文件属性(OS管理文件) 2.3…

线性时变系统的PID控制-2

在线性时变系统的PID控制-1的基础上采用S函数进行Simulink仿真。被控对象的描述方式可变换为&#xff1a;在S函数中&#xff0c;采用初始化、微分函数和输出函数&#xff0c;即mdllnitializeSizes函数、mdIDerivatives函数和mdlOutputs函数。在初始化中采用sizes结构&#xff0…

力扣sql简单篇练习(三)

力扣sql简单篇练习(三) 1 查找重复的电子邮箱 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 SELECT Email FROM Person GROUP BY Email HAVING count(id)>21.3 运行截图 2 每个产品在不同商店的价格 2.1 题目内容 2.1.1 基本题目信息 2.1.2 示…

[经典的图像warping方法] Thin Plate Spline: TPS理论和代码详解

0. 前言 2022年没有新写什么博客, 主要精力都在搞论文. 今年开始恢复! 本文的目标是详细分析一个经典的基于landmark(文章后面有时也称之为控制点control point)的图像warping(扭曲/变形)算法: Thin Plate Spine (TPS). TPS被广泛的应用于各类的任务中, 尤其是生物形态中应用…

动态内存管理(C语言)

目录 为什么要存在动态内存分配 动态内存函数的介绍 malloc函数 free函数 calloc函数 realloc函数 常见的动态内存错误 对NULL指针解引用错误 对动态开辟的空间越界访问 对非动态开辟内存使用free释放 使用free释放一块动态开辟内存的一部分 对同一块动态内存多次释放 动态开辟…

客快物流大数据项目(一百零五):启动ElasticSearch

文章目录 启动ElasticSearch 一、启动ES服务端 二、​​​​​​​启动Kibana 启动ElasticSearch

【NI Multisim 14.0虚拟仪器设计——放置虚拟仪器仪表(频率计数器)】

目录 序言 &#x1f3ee;放置虚拟仪器仪表&#x1f3ee; &#x1f9e7;频率计数器&#x1f9e7; &#x1f973;&#x1f973;&#xff08;1&#xff09;“测量”选项组:参数测量区。 &#x1f973;&#x1f973;&#xff08;2&#xff09;“耦合”选项组:用于选择电流耦合方…

CSDN 的故障处理流程,实例分享

CSDN 的研发团队每隔一段时间会和大家分享团队的进展&#xff0c;请看&#xff1a; 2021 年年底的汇报 2022 年上半年的汇报 2022 年下半年的汇报 从上面的报告中大家可以看到&#xff0c;我们在取得进展的同时&#xff0c; 也碰到了很多问题&#xff0c;也有一些困惑。 我写了…

「链表」简析

前言 前言&#xff1a;研究一个数据结构的时候&#xff0c;首先讲的是增删改查。 文章目录前言一、链表简介1. 含义2. 节点组成3. 存储方式1&#xff09;数据在内存中的存储方式2&#xff09;单链表在内存中的存储方式3&#xff09;双链表在内存中的存储方式4&#xff09;循环链…

ZYNQ IP核之MMCM/PLL

锁相环&#xff08;Phase Locked Loop&#xff0c;PLL&#xff09;&#xff0c;一种反馈控制电路&#xff0c;对时钟网络进行系统级的时钟管理和偏移控制&#xff0c;具有时钟倍频、分频、相位偏移和可编程占空比的功能。 Xilinx 7系列器件中的时钟资源包含了时钟管理单元CMT&…

SAPIEN PrimalSQL 2023.1[x64] Crack

SAPIEN PrimalSQL 2023.1 使数据库查询开发和测试变得轻而易举&#xff0c;无论您的数据库类型或供应商如何。 通过单个工具支持多个数据库提供程序。 Access、SQL Server、SQL Server Compact、MySQL、Oracle、ODBC、OLEDB、Sybase 等。 使用Visual Query Builder构建复杂的…

maven基础

一、Maven基础 为什么要学习Maven&#xff1f; Maven作为依赖管理工具&#xff0c;能够管理大规模的jarjarjar包&#xff0c;使用MavenMavenMaven后&#xff0c;依赖对应的JarJarJar包&#xff0c;能够自动下载、方便、快捷切规范。Maven作为构建管理工具&#xff0c;当我们使…

HTTP实用指南

HTTP实用指南 01.初始HTTP 当我们在浏览器地址栏输入一个网址或者关键字&#xff0c;它会给我们跳转到对应的网页&#xff0c;在这一过程中&#xff0c;内部到底是怎么运作的&#xff1f; 总结上述图片过程&#xff0c;用流程图来表示&#xff0c;如下&#xff1a; 处理输入信…

【论文翻译】Semantic Graph Convolutional Networks for 3D Human Pose Regression

【iccv论文】https://openaccess.thecvf.com/content_CVPR_2019/papers/Zhao_Semantic_Graph_Convolutional_Networks_for_3D_Human_Pose_Regression_CVPR_2019_paper.pdf 【github】https://github.com/garyzhao/SemGCN 摘要 在本文中&#xff0c;我们研究了用于回归的图卷积网…

ANR触发机制分析

ANR是一套监控Android应用程序响应是否及时的机制&#xff0c;可以把发生ANR比作是引爆炸弹&#xff0c;那么整个流程包含三部分组成&#xff1a; 埋定时炸弹&#xff1a;system_server进程启动倒计时&#xff0c;在规定时间内如果目标应用进程没有干完所有的活&#xff0c;则…

QEMU之一调试uboot(vexpress-a9)

u-boot版本&#xff1a;u-boot-2017.05开发板&#xff1a;vexpress-a9&#xff08;没办法&#xff0c;目前看到的都是这个开发板&#xff0c;想QEMU调试tiny210,一直没看到怎么修改qemu&#xff09;编译u-boot&#xff1a;make ARCHarm CROSS_COMPILEarm-linux-gnueabi- vexpre…

Avast 发布免费的 BianLian 勒索软件解密器

安全软件公司 Avast 发布了 BianLian 勒索软件的免费解密器&#xff0c;以帮助恶意软件的受害者在不向黑客支付费用的情况下恢复锁定的文件。 在 2022 年夏天 BianLian 勒索软件的活动增加后大约半年&#xff0c;该威胁组织入侵了多个知名组织&#xff0c;解密器的可用性就出现…

swagger(前言技术)

目录 一、swagger简介 1.前后端分离的特点 2.在没有swagger之前 3.swagger的作用 4.swagger的优点 二、swagger入门 1.新建springboot项目 2.集成swagger 3.开发一个controller用于测试 5.启动服务&#xff0c;验证集成效果 三、swagger常用注解 四、swagger使用综…

2022年PTA行业研究报告

第一章 行业概况 PTA是精对苯二甲酸&#xff08;Pure Terephthalic Acid&#xff09;的英文简称&#xff0c;在常温下是白色粉状晶体, 无毒、易燃&#xff0c;若与空气混合&#xff0c;在一定限度内遇火即燃烧。 PTA是重要的大宗有机原料之一&#xff0c;广泛用于化学纤维、轻…

【数据结构入门】-线性表之顺序表(1)

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【数据结构】 从今天开始&#xff0c;就正式进入数据结构的大门了&#xff0c;把握机会&#xff0c;好好学习&#xff0c;加油。 本文目录…