IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++学习 六、指针 -> 正文阅读

[C++知识库]C++学习 六、指针

前言

指针是C,C++与其它语言的一大区别,也是C++程序设计里的难点。

本篇学习C++指针的基本用法。

指针与地址

地址是内存空间的位置,指针是保存地址的特殊数据类型。

广义的说,指针就是地址,指针变量用于存储地址。

狭义的说,地址就是内存空间的编号,而指针有具体的存储数据类型(比如int *p;),因此指针不完全是地址。

指针使用

声明指针

声明指针必须说明是指向什么数据类型的指针(这样才能确定数据在内存空间的使用量):

int *p_int;
double *p_double;

指针变量的创建细节

声明指针时,计算机会给指针变量分配内存空间用于存储地址,但是不会给指针指向的数据分配内存空间,下面的使用方法将报错:

int *p_n;
*p_n = 0;

声明指针p_n时,系统给p_n分配了内存空间,其地址为addr1,存储的是p_n;但系统没有在p_n存储的地址addr2分配空间,因此addr2是个未定值,系统不知道把0放到哪个地址上,因而报错。

取地址符

&被用于取得变量的地址:

int variable = 0;
std::cout << &variable;

初始化

可以在声明指针时初始化指针:

int a = 2;
int *p_a = &a;

指针p_a被初始化,获得a的地址,指向变量a

赋值

可以通过赋值运算符,把地址赋给指针:

int b = 2;
int *p_b;
p_b = &b;

指针的整形赋值

计算机将指针当作整数处理,但指针和整形是两种不同的数据类型,指针没有乘除计算。因此不能简单的把整形赋给指针,必须使用强制类型转换:

int *p_s = (int *) 0x10000000;

算术运算

指针有加减法:

int *pp = new int;
cout << (pp + 1); // pp地址后的一个位置

比如pp=0x10000000,pp + 1 = 0x10000004,即地址增加了4个字节的长度(int类型长度)。

在数组中的两个元素的指针相减,能得到两个元素的间隔。

指针解引用(取值运算符)

*除了是指针类型名,还用于取得指针指向的数据,也叫指针的解引用:

double c = 5.2f;
double *p_c = &c;
std::cout << *p_c;

区分指针类型与解引用

在声明和初始化中,*表示声明的是指针类型。

在指针变量被声明和赋值后,*表示的是指针解引用。

short d = 1;
short *p_d = &d; // 声明指针类型
*p_d; // 解引用

动态内存分配

定义变量是一种分配内存空间的方法(自动变量,栈空间):

int e = 5; // 在栈空间中分配内存
int *p_e = &e;

使用new是另一种分配内存空间的方法(动态存储,堆空间):

int *p_f = new int;

new TypeName在内存空间中找到一块满足TypeName类型的块,返回内存空间的地址。

动态数组

new TypeName []用于创建动态数组:

int *p_vec = new int [10];

``delete []````用于释放动态数组空间:

delete [] p_vec;

动态内存释放

动态分配的内存空间,如果不需要再使用时,要及时通过delete释放,new,delete要成对使用。否则容易出现内存泄漏memory leak。

delete不会把指针删除,而是释放指针指向的内存空间。空间释放后,最好把指针置空:

int *p_g = new int;
delete p_g;
p_g = nullptr;

delete不能释放栈空间上的内存,但是可以delete空指针。

也不能对同一个指针释放两次,会报double free的错误。

C++11推出了智能指针,能够降低内存泄漏的风险。

数组名与指针

C++中,数组和指针基本是等价的,数组名表示数组第1个元素的地址。区别在于,数组名的值是不能改变的,但指针变量的值是可以改变的。通过指针访问数组元素:

p_vec[1] = 1; // 使数组第2个元素为1;
*(p_vec + 1) = 1; // equal;

需要注意,对数组使用sizeof得到数组长度,对一个指向数组的指针应用sizeof得到指针长度。

指针数组与数组指针

指针数组

指针数组,变量名表示一个数组,也就是数组中的每个元素都是一个指针,:

int* vec_p[5];

上面这个声明中,[]*的优先级高,因此vec_p[5]是一个数组,而int*指定了数组类型为整形指针。

指针数组常用于字符串数组:

char* vec_string[2] {"Hello, ", "World!"};

数组指针

数组指针,变量名表示一个指针,指向整个数组:

int (*p_vec)[10];

上面这个声明中,首先声明了p_vec是一个指针,指向一个10元素整形数组。此时,p_vec + 1是p_vec地址后40个字节的位置。

数组指针常用于多维数组(比如OpenCV中Mat数据读取),举个二维数组的例子:

ushort pixel[5][10];
ushort (*p_pixel)[10] = pixel;
(*(p_pixel + 2))[4] = 3 // 设置第3行,第5列数据的值为3
std::cout << (*(p_pixel + 2))[4]; // 输出第3行,第5列数据的值

p_pixel[2][4] = 3; // equal

对数组取地址

数组名表示数组首元素的地址,对数组取地址也会获得数组的地址,但二者的含义是不一样的:

int vec[5] {0, 1, 2, 3, 4};
std::cout << vec << "\n";
std::cout << &vec << "\n";

std::cout << (vec + 1) << "\n";
std::cout << (&vec + 1) << "\n";

结果:

0x7ffe8742ebd0
0x7ffe8742ebd0
0x7ffe8742ebd4
0x7ffe8742ebe4

取数组的地址时,返回的是整个数组的地址,也就是包含5个int元素的地址,&vec + 1的地址为数组首元素地址 + 5 * 4

而数组名,就是数组首元素的地址,vec + 1的地址为数组首元素地址 + 4

后记

本篇记录了C++中指针的基本使用,以及指针和数组的关系,下一篇将继续记录指针与字符串的关系。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 18:45:28  更:2022-01-30 18:46:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 8:39:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码