九、C++ 指针 pointer 引用 Reference

2023-05-16

原始指针 raw pointer 非智能指针 smart pointer

指针是一个整数,一个数字,它存储一个内存地址。

创建指针:void* ptr = 0;

void指针表明不关心指针存储地址的数据类型。给该指针一个为0的内存地址,0其实不是一个有效的内存地址,没有办法读取或写入地址为0的内存。0无效意味着该指针无效。对指针来说,无效是可以接受的。指针为0也可以是NULL,# define NULL 0。C++中一个关键字叫做nullptr。

#include <iostream>

int main()
{
	void* ptr = nullptr;//该指针完全没有类型,内存地址为0
	std::cin.get();
}

程序中创建一个整数变量,该变量有一个内存地址,内存地址存储该变量。若要知道变量的存储地址,可以通过“&”运算符来实现。得到变量的存储地址存储在一个指针中。

#include <iostream>

int main()
{
	int var = 8;
	void* ptr = &var;//将变量var的内存地址作为指针赋给ptr变量
	std::cin.get();
}

设置断点查看值

将ptr的值进行复制,然后调试-窗口-内存-内存1

 该窗口将显示程序内的所有内存,将复制来的ptr的地址输入然后回车,就搜索到该地址。

 该内存地址有8,因为我们创建了那个变量并且设置为8。该指针存放的地址里面的值为8。

指针是一个包含地址的变量。

指针可能是一个32、16、64位的整数。如果指针是void指针,计算机不会知道这个指针指的内存是几个字节,也就没有办法向这个内存中存入数据,此处就要牵涉到指针类型了。

#include <iostream>
#define LOG(x) std::cout << x << std::endl

int main()
{
	int var = 8;
	int* ptr = &var;//将变量var的内存地址作为指针赋给ptr变量
	*ptr = 10;//解引用指针,访问指针的内存数据,读取或写入
		LOG(var);
	std::cin.get();
}

通过解引一个指针并写入它,实际就是在访问该块数据,写入该块内存。在实际的指针中,并没有说内存有多大。只有创建数组的时候会记录大小。以上创建的指针都是存内存的stack部分创建它,也可以在heap上创建变量。

向计算机申请指定大小的内存:char*  ,char是一个字节。char* buffer = new char[8];//申请八个字节的内存,并返回指向这块内存的开始地址的指针

使用memset:用指定数据填充一块内存,接受一个指针buffer,该buffer指针指向这块内存的开始处。然后接受一个值,比如0。之后是填充字节,此处为8字节。memset(buffer,0,8);

#include <iostream>
#define LOG(x) std::cout << x << std::endl

int main()
{
	char* buffer = new char[8];
	memset(buffer,0,8);
	std::cin.get();
}

由于使用了new这个关键字,所以该数据是分配在heap上的。 new[]和delete[]都是在heap上操作内存,最后还可以用buffer = nullptr;回收指针

指针的指针,一个变量存储着一个内存地址,它指向一个变量,这个变量也存储着一个内存地址。

创建一个double pointer(指针的指针)

int main()
{
	char* buffer = new char[8];
	memset(buffer,0,8);

	char** ptr = &buffer;//ptr属于指针的指针,
	delete[] buffer;//使用的是new[]来分配的,应该使用delete[]来删除
	std::cin.get();
}

设置断点。根据ptr的地址搜索,然后,搜索到的地址由于电脑是小端的所以要逆序排,

(例如此处按照指针的指针搜索到的指针的地址是60 f6 bf 00,按照指针的地址搜索指针指向的值的时候就要输入00 bf f6 60进行搜索,得到指针指向的地址存储的buffer的值0)

 

到达buffer的内存位置。

16

Reference 引用 指针的扩展

在计算机如何处理两种关键字的角度看,指针和引用基本上是一回事。

引用:是指对某个已存在的变量的引用。对于指针来说可以创建指针变量并赋值nullptr或者其他等于0的量,但是引用不能。“引用变量”必须引用一个已存在的变量,它本身不是一个新的变量,并不真正占用内存,只是其他变量的引用。

引用时,创建变量类型+&,中间不加任何符号包括空格,例“int&”,&符号实际上是变量类型的一部分。

#include <iostream>
#define LOG(x) std::cout << x << std::endl

int main()
{
	int a = 5;//创建变量
	int& ref = a;//创建变量的引用
	ref = 2;
	LOG(a);//a的值变为2
	std::cin.get();
}

创建了一个别名,因为这个ref“变量”不是变量,而是别称。ref变量并不真正存在,只存在于我们的源码里。ref可以与a一样使用。

 在任何情况下,ref就是a,只是给a创建了一个别名。此处的引用并不是一个指针,只是在源码中的一种操作,如果我们希望给某个变量一个别名,引用更方便写代码。

假设想要一个函数使输入的整数递增。

#include <iostream>
#define LOG(x) std::cout << x << std::endl
void Increment(int value)
{
	value++;
}

int main()
{
	int a = 5;
	Increment(a);//传值调用,调用过程中程序会拷贝参数值5到这个函数中
	LOG(a);//a的值没有发生改变,value的值发生改变
	std::cin.get();
}

结果是5,值没有改变。

由于想要引用传递(passing by reference) 这个变量来让他递增,故要改变a的值。通过向Increment函数中不是传递5、而是传递a这个变量的地址。通过函数找到这个变量的地址,找到变量的值5,然后加以更改。把内存地址传进函数,通过内存地址完成写入。做法:把函数的形参变成一个指针。在调用函数时会将a的内存而不是a本身传递给函数。

#include <iostream>
#define LOG(x) std::cout << x << std::endl
void Increment(int* value)//函数的形参变成一个指针
{
	(*value)++;//改为解引用的形式从而改变地址存储的数值,而不是地址本身。递增符号优先级高于引用
}

int main()
{
	int a = 5;
	Increment(&a);//在调用函数时会将a的内存而不是a本身传递给函数。
	LOG(a);
	std::cin.get();
}

输出值为6

另一种方法,直接引用:

#include <iostream>
#define LOG(x) std::cout << x << std::endl
void Increment(int& value)//将指针形参改为引用的形式
{
	value++;//不需要使用解引用形式
}

int main()
{
	int a = 5;
	Increment(a);//只需要传递a
	LOG(a);
	std::cin.get();
}

结果仍然是6

一旦声明了一个引用,就不能更改它所引用的对象;声明一个引用时,必须将一个实际变量赋值给它,不能只声明不赋值。

17

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

九、C++ 指针 pointer 引用 Reference 的相关文章

  • 引用的项目在编译时“丢失”

    我有一个包含两个项目的 C 解决方案 一个服务 主项目 和一个记录器 该服务使用记录器中的类 我在服务项目中添加了对记录器项目的引用 在设计时 自动完成工作正常 记录器的类是可见的 我使用的引用具有适当的颜色 我重建解决方案 但出现问题 不
  • Java 中的引用变量里面有什么?

    我们知道对象引用变量保存表示访问对象的方式的位 它不保存对象本身 但保存诸如指针或地址之类的东西 我正在阅读 Head First Java 第 2 版 一书 书中写道 第 3 章第 54 页 在 Java 中我们并不真正知道什么是 在引用
  • 为什么链接生命周期仅与可变引用相关?

    前几天 有一个问题 https stackoverflow com questions 32089410 lifetimes and references to objects containing references有人对包含借用数据本
  • 找到的程序集的清单定义与程序集引用不匹配

    我试图在 C Windows 窗体应用程序 Visual Studio 2005 中运行一些单元测试 但出现以下错误 System IO FileLoadException 无法加载文件或程序集 实用程序 版本 1 2 0 200 文化 中
  • Java:等于和==

    让我们看看我们有 2 个对用户定义类实例的引用 即 Java 中的 a 和 b 会不会有一种情况 a b 但 a equals b 返回 false 当然 实施 equals 完全取决于班级 所以我可以写 class Foo public
  • Android - 存储对ApplicationContext的引用

    我有一个静态 Preferences 类 其中包含一些应用程序首选项和类似的内容 可以在那里存储对 ApplicationContext 的引用吗 我需要该引用 以便我可以在不继承 Activity 的类中获取缓存文件夹和类似内容 你使用的
  • 对象指针值作为字典的键

    我想使用对象的引用值作为字典的键 而不是对象值的副本 因此 我本质上想在字典中存储与另一个对象的特定实例关联的对象 并稍后检索该值 这可能吗 是不是完全违背了NSDictionary的理念 我可以看出我可能以错误的方式处理这个问题 因为字典
  • C++ 在 std::map 中存储对值的引用

    我是否正确地假设向 std map 添加 删除元素不会影响其他元素 即导致它们在内存中重新定位 因此以下内容是安全的 我查看了各个网站上有关容器的信息 但只发现了迭代器无效的情况 这是我已经知道的 std map
  • 为什么选择 & 符号作为 C++ 中的引用符号? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有谁知道为什么在 C 中选择 符号作为表示引用的方式吗 AFAIK 虽然我附近没有这本书 Stroustroup 没有解释这个选择 我觉得这有点
  • 我在使用 ado.net 时收到错误 Argument 2 may not be pass with ref keywords

    int t 0 cmd Parameters AddWithValue Res ref t 我在第二行收到错误 参数 2 不能与 ref 关键字一起传递 您只能通过引用传递参数ref if the 范围 is a ref参数也是如此 Add
  • 从函数返回哈希值的最佳 Perl 实践是什么?

    我正在考虑将哈希引用传递给函数或从函数返回数据的最佳实践 一方面 仅将输入值传递给函数并仅返回输出变量似乎很直观 然而 在 Perl 中传递哈希值只能通过引用来完成 因此有点混乱 而且似乎更有可能犯错误 另一种方法是在输入变量中传递引用 但
  • 在 perl 中 \*STDIN 与 STDIN 相同吗?

    我是作者Python化者 https github com snoopyjc pythonizer我正在尝试将 CGI pm 的代码从标准 perl 库翻译为 Python 我在中遇到了这段代码从客户端读取 https metacpan o
  • 术语“引用”的起源,如“通过引用传递”

    Java C 语言律师喜欢说他们的语言按值传递引用 这意味着 引用 是调用函数时复制的对象指针 同时 在 C 中 以及 Perl 和 PHP 中更动态的形式 引用是其他名称 或动态情况下的运行时值 的别名 我对这里的词源感兴趣 参考 一词的
  • NuGet 将项目依赖项打包为 nuget 依赖项

    我有 3 个类库项目 都是 NET Standard 2 0 它们都在同一个解决方案中 我想将它们打包成一个 nuget 并在其他存储库中使用代码 但是 当我将它们打包到 NuGet 包中时 其中两个将作为 nuget 依赖项添加到第三个包
  • 带有参考的 Haskell 数据类型

    我正在实现 Ukkonen 的算法 该算法要求树的所有叶子都包含对同一整数的引用 并且我在 Haskell 中执行此操作是为了了解有关该语言的更多信息 但是 我很难编写出执行此操作的数据类型 Node has children indexe
  • 将非 GAC 引用添加到项目中

    每次我在 Visual Studio 2008 中添加对 GAC 中的 Web 项目的引用时 它都会将该引用添加为 GAC 引用 并且不会将该文件复制到我的 bin 目录中 但出于部署目的 我想将引用添加为非 GAC 引用 以便将 dll
  • 函数原型和数组参数

    我正在学习 C 语法 并且已经开始研究数组了 我想问你一个问题 但首先让我回顾一下 这样我就知道我已经弄清楚了 我知道您可以使用以下语法将变量定义为数组 name
  • 为什么 32 位 .NET 进程的引用类型的最小大小为 12 字节

    我正在读专业 Net 性能 https rads stackoverflow com amzn click com 1430244585本书有关参考类型内部结构的部分 它提到 对于 32 位 net 进程 引用类型具有 4 字节的对象头和
  • 如何通过 *.csproject 文件查找参考路径

    我想制作一个自动化的 powershell 脚本 报告项目的引用和引用路径 当 csproj 中的提示路径未填写时 我找不到获取引用路径的方法 这是一个快速解决方案 它抓住了每一个 csproj当前目录下的文件 并检查每个引用 对于从 GA
  • C++ 返回值、引用、const 引用

    你能向我解释一下返回值 值引用和值常量引用之间的区别吗 Value Vector2D operator const Vector2D vector this gt x vector x this gt y vector y return t

随机推荐

  • 大疆遥控控制M3508电机二(基于HAL库)

    接上一篇文章 xff0c 话不多说直接开始 一 打开我们创建的工程文件 xff0c 先就建立一个文件夹用来存放我们写的子文件 xff08 不建立也行 xff09 xff0c 然后建立pid h xff0c pid c存入我们建立的文件夹中
  • aruco_ros 在相机图像中显示的坐标轴姿态与TF发布的姿态不一致 解决方法

    aruco ros 在相机图像中显示的坐标轴姿态与TF发布的姿态不一致 解决方法 运行环境问题描述解决方案 运行环境 系统版本 xff1a Ubuntu 16 04 ROS版本 xff1a Kinetic 问题描述 在进行手眼标定过程中 x
  • 安装vscode的时候没有勾选快捷方式用vscode打开文件,如何用vscode快速打开文件或者文件夹

    1 需要在注册表里面添加内容可以实现 xff0c 下面有一种简单的方式来完成这个操作 2 需要在电脑桌面新建一个Open File With VS code reg 文件然后用打开文件 xff0c 将以下代码复制 Windows Regis
  • C语言学习笔记->const和define区别

    1 define 是预编译指令 xff0c 而const 是普通变量的定义 define定义的宏是在预处理阶段展开的 xff0c 而const定义的只读变量在编译运行中使用 2 const定义的是变量 xff0c 而define定义的是常量
  • 基于栈、寄存器的优缺点

    基于栈的优点 xff1a 对硬件的依赖不高 xff0c 跨平台性 缺点 xff1a 使用的指令集高基于寄存器的优点 xff1a 相对于栈来说 xff0c 寄存器的性能高 xff0c 使用的指令集少 Java代码执行流程 xff1a java
  • Makefile文件的编写(实例详解)

    1 什么是Makefile xff1f 一个工程中的源文件不计其数 xff0c 其按类型 功能 模块分别放在若干个目录中 xff0c Makefile定义了一系列的规则来指定哪些文件需要先编译 xff0c 哪些文件需要后编译 xff0c 哪
  • 用C语言实现万年历的代码及思路(详细教程)

    万年历程序要求 xff1a 1 当选择1的时候 xff0c 输入年 xff0c 打印输入的这一年12月的日历 2 当选择2的时候 xff0c 输入年 月 xff0c 打印输入这一年这一月的日历 实现效果 xff1a 选择1时 span cl
  • 有符号数和无符号数参与运算时的问题

    陷阱题目 xff1a 下面的代码输出是 xff08 xff09 span class token macro property span class token directive hash span span class token di
  • 【Linux网络编程】基于UDP实现多人聊天室

    文章目录 一 UDP的概念1 1 UDP1 2 UDP特点 二 采用UDP实现多人聊天室原因三 多人聊天室项目功能四 实现多人聊天室项目流程分析4 1 前期准备4 1 1 定义结构体4 1 2 定义链表 4 2 多人聊天室服务器4 2 1
  • 【C++】C向C++的知识过度(上)

    文章目录 一 C与C 43 43 的区别1 1 C是面向过程的1 2 C 43 43 是面向对象的1 3 编译器的区别 二 C与C 43 43 默认代码的不同三 命名空间3 1 关键字 96 namespace 96 去定义自己的名字空间
  • 【C++】四种类型转换 | C++异常处理机制 | C++11新特性之右值引用和移动构造

    文章目录 一 C 43 43 中的四种类型转换1 1 静态类型转换1 1 1 C 43 43 中内置类型的转换1 1 2 C 43 43 中的有继承关系存在的场景下的类型强转 1 2 动态类型转换1 3 常类型转换1 4 解释类型转换 二
  • 【Linux操作系统】进程详解(上)

    文章目录 一 进程的定义二 进程的特征三 进程的组成及其作用四 进程控制块4 1 进程控制块定义4 2 task struct的内容 五 进程与程序的区别六 进程与线程的区别七 进程的种类八 PID8 1 PID定义8 2 特殊PID的进程
  • 【Linux操作系统】进程详解(下)

    文章目录 前言一 父子进程共用光标问题1 1 验证1 2 规避共用光标问题使用多进程拷贝同一个文件 二 进程相关函数2 1 getpid getppid函数2 2 exit exit函数2 3 wait waitpid函数 三 守护进程3
  • git补丁操作(git diff、git format-patch、git apply、git am)

    https blog csdn net qq 42138454 article details 119058431 实际使用补丁用的 xff1a patch p1 lt device nuwa diff 一 打补丁的两种方法 Git 提供了
  • 三、C++ 链接器 linker

    cilinking 从C 43 43 源码到可执行二进制的过程 compile文件之后进行链接 xff0c 找到每个符号 函数的位置 xff0c 并将其链接在一起 每个文件被编译成一个独立的 obj文件作为translation unit
  • 五、C++中的头文件 Header Files

    头文件 Header Files传统上用于声明某些函数类型 xff0c 以便可以用于整个程序中 例如 xff1a 在一个文件1中创建函数 xff0c 然后想在另一个文件2中使用 xff0c 尝试编译此文件2时 xff0c C 43 43 不
  • 六、如何使用VS调试代码、条件语句

    how to use Visual Studio to debug our code 查看程序断点 调试程序 1 设置断点 断点 xff0c 调试器将中断 xff0c break xff0c 程序调试是将会中断 xff0c continue
  • 七、如何设置C++项目 set up C++ project

    Visual Studio设置项目文件目录 组织项目文件 打开Visual Studio Start Page 起始页 xff0c 新建项目 New Project xff0c C 43 43 下的General Empty Project
  • 八、C++中的循环 for while do...while及控制流语句

    xff08 1 xff09 for while do while循环 简单来讲 xff0c 循环就是多次执行同样的代码 例 xff0c 如何输出重复内容多次 xff1a 代码复制多次 xff1b 写个函数调用多次 xff1b 写循环重复执行
  • 九、C++ 指针 pointer 引用 Reference

    原始指针 raw pointer 非智能指针 smart pointer 指针是一个整数 xff0c 一个数字 xff0c 它存储一个内存地址 创建指针 xff1a void ptr 61 0 void指针表明不关心指针存储地址的数据类型