iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++中指针与引用的区别是什么
  • 774
分享到

C++中指针与引用的区别是什么

2023-06-19 13:06:07 774人浏览 安东尼
摘要

这篇文章主要介绍了c++中指针与引用的区别是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++中指针与引用的区别是什么文章都会有所收获,下面我们一起来看看吧。1、指针的声明上文中提到,指针和其所指向的变量

这篇文章主要介绍了c++中指针与引用的区别是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++中指针与引用的区别是什么文章都会有所收获,下面我们一起来看看吧。

1、指针的声明

上文中提到,指针和其所指向的变量就像硬币的两面,因此通过取址符号"&"我们可以找到变量的地址,通过解引用符号"*"可以找到地址内存放的变量值。

int data = 10; //声明了一个变量data,并赋初始值10,存储的值是int类型int* p_data = &data; //找到 data 在内存中存放的位置,即p_datacout << "地址为:" << int(p_data) << " 存放的值为:" << data << endl;

输出结果为:

地址为:8191436  存放的值为:10

地址默认是16进制,我们在输出时将其转换成了int 类型,因此以十进制输出。输出结果翻译过来就是:在地址编码为8191436的位置存放了值为10的变量data,再进一步地说,data与*p_data 表示同一个东西。为了更有助于理解,我们绘制了下图:

C++中指针与引用的区别是什么

因此从本质上看,指针与普通的变量并没有什么太大的区别,只是指针变量可以通过解引用的方式找到指针所对应的地址中存放的数值。假如定义如下:

int data = 10;int* p_data = &data;  //定义指向 int 类型的指针 p_data, 存储的是 int 类型的变量 data的地址,其int** p_p_data = &p_data; //定义指向 int* 类型的指针 p_p_data, 存储的是 int* 类型的变量 p_data的地址cout << "p_data:" << p_data << " 存放的值为:" << *p_data << endl;cout << "p_p_data:" << p_p_data << " 存放的值为:" << *p_p_data << endl;

输出结果为:

p_data:00EFF96C         存放的值为:10
p_p_data:00EFF960       存放的值为:00EFF96C

从输出结果可以看出,p_p_data中存储的值就是p_data,而p_data中存储的值就是data,很像”我爱她,她爱他“的这种桥段。下面我们就重点分析一下变量与指针之间的关系:我们在上述例子中把指针初始化为变量的地址,而变量是在编译时分配的有名称的内存,指针只是为可以通过名称直接访问的内存提供了一个别名。还拿上面这个例子:对程序员来说,变量10的名字就是data;而对于计算机来说,变量10就是存在 8191436 地址的数据;实现程序员与计算机沟通的方式就是指针,通过对data取址让程序员能够明白计算机的存储结构,同样,通过对地址解引用,也能轻松地找到该地址中存储的数据。在上述情况下,指针的出现显得有些多余,然而指针的真正用武之地在于,在运行阶段分配未命名的内存以存储值,在这种情况下,只能通过指针来访问内存。

最后关于指针声明的一点建议:在声明一个指针变量时,必须要指定一个确定的地址,否则声明的指针变量不知道指向哪里,因此容易造成系统崩溃。

2、使用new来分配内存

内存四区之代码区,全局区,栈区和堆区中提到过,new 会在堆区创建一个内存空间,其返回值就是该内存空间的地址,因此程序员的责任就是将该地址赋给一个指针。下面是一个示例:

int* p_data = new int; //在堆区开辟一个空间,并返回该内存空间的地址*p_data = 10; //将向该内存中存储数值10cout << "p_data:" << p_data << " *p_data: " << *p_data << endl;

通过比较会发现,new 后面指定了数据类型 int,同样地,p_data 也被声明为指向 int 的指针。这是因为,计算机的内存是以字节为存储单位,不同类型的变量会占用不同的字节,因此使用 new 时必须要告诉编译器分配多少字节的存储空间,并且接收的指针也必须与声明的类型一致。输出结果为:

p_data: 00D0D9A0         *p_data: 10

当处理大型数据,比如数组时,通常会使用的一种方法是定义一个数组类型的数据,在定义的时候分配足够大的空间。但是这种做法太过于死板,但是当使用 new 时,如果在运行阶段需要数组,那么则创建它,如果不需要则不创建,最重要的是可以在程序运行时选择数组的长度。 下面就看一下如何使用 new 来创建动态数组。在C++中,数组名被解释为数组地址,即数组第一个元素的地址。下面是一个实例:

int Arr[10]; // 定义一个包含10个int类型元素的数组cout << "Arr:" << Arr << "&Arr[0]:" << &Arr[0] <<endl;

输出结果为:

Arr:008FFAB4    &Arr[0]:008FFAB4

这种声明方式只能在刚开始就声明固定的数组长度,在C++中创建动态数组时,只需要将数组的元素类型和元素数目告诉给 new 即可,new 的返回值同样是数组的首地址。

int ele_num = 10; //临时指定数组内元素的个数int* p_arr = new int [ele_num]; //根据临时指定的元素个数创建数组

通过 new 在堆区开辟空间,由程序员管理释放,因此当 new 的内存不用后,需要通过 delete 进行变量,使用 delete [] 来释放开辟的数组空间。代码如下:

int* p_data = new int;*p_data = 10;cout << "p_data: " << p_data << "*p_data:" << *p_data << endl;int ele_num = 10;int* p_arr = new int [ele_num];for(int i = 0; i<9; i++) *(p_arr+i) = i+2;cout << "p_arr:" << p_arr << "*(p_array):";for(int i = 0; i<9; i++) cout << *(p_arr + i) << " ";cout << endl;delete p_data;delete [] p_arr;cout << "******使用delete释放内存后......*******" << endl;cout << "p_data: " << p_data << "*p_data:" << *p_data << endl;cout << "p_arr:" << p_arr << "*(p_array):";for(int i = 0; i<9; i++)cout << *(p_arr + i) << " ";cout << endl;

输出结果如下:

p_data: 0082B1C8        *p_data:10
p_arr:0082BB58          *(p_array):2 3 4 5 6 7 8 9 10

******使用delete释放内存后......*******
p_data: 0082B1C8        *p_data:-572662307
p_arr:0082BB58          *(p_array):-572662307 -572662307 -572662307 -572662307 -572662307 -572662307 -572662307 -572662307 -572662307

3、malloc 与 new 的区别

学过C语言的朋友都知道,在C语言中通过malloc函数开辟一块内存空间,malloc的函数原型如下:

void* malloc(unsigned int numbytes);

从函数原型的参数可以看出,malloc 函数以字节数为参数,开辟固定字节的内存空间。这与 new 就有了第一点不同:new 不需要自己计算字节数,只需要给定内存中存储的数据类型与元数个数即可。

从函数原型的返回类型可以看出,malloc 函数返回 void* 类型,需要我们在使用时自己指定指针类型。比如:

int* p_malloc = nullptr; // 创建一个指向int的指针p_malloc = (int*) malloc(10); //将 malloc 的返回值强制转换为 int* 类型

而 new 在使用时则不需要。总结看来,malloc 在使用时需要自己根据内存中的数据类型以及内存长度计算处所需要的字节数,然后返回 void* 类型,需要使用对应类型的指针进行接收。而 new 在使用时只需要给定内存的长度与内存中数据的类型,编译器会自动计算所需要的字节数。

4、引用的声明与本质

C++中新增了引用作为已定义的变量的别名。引用的最主要用途是作为函数形参,这样函数就可以使用原始数据而不是数据副本,这样听起来似乎与指针没什么区别,我们还是从引用的声明说起。

int data = 10;int& p_data = data; //创建一个引用变量 p_datacout << "data:" << data << "p_data:" << p_data << endl; //p_data 与 data 相当于一个变量的两个名字

输出结果为:

data:10  p_data:10

从输出结果来看,p_data 与 data 就是一个变量的两个不同叫法而已。引用必须在声明时就为其指定初始值,而不能像指针一样可以先声明,再赋值。下面将引用作为函数的参数来进一步说明引用与指针的区别:

template <typename T> //定义一个模板函数void swap(T a, T b){ int temp; temp = a; a = b; b = temp;}int main(void){ int a = 10, b = 20;  swap_value<int>(a,b); //首先进行值传递 cout << "a:" << a << "b:" << b << endl; swap_value<int&>(a,b); //然后进行引用传递 cout << "a:" << a << "b:" << b << endl;}

从上述代码中可以看到,值传递和引用传递的形参都是一样的,不同的是引用传递时,实参被声明为引用,引用的用法与使用值一模一样,输出结果如下:

a:10            b:20
a:20            b:10

惊奇的发现,引用传递改变了原始数据的值,这点与指针的用法一致,但是指针在书写 swap 函数时应该这样写:

void swap(int* a, int* b){ int temp; temp = *a; *a = *b; *b = temp;}swap(&a, &b); //调用格式

综上发现,引用其实就是变量的另一个名称,它的用法与变量一模一样,但是能在作为形参传递时,改变原始数据的值。除了这些用法上的区别,引用的本质其实就是一个指针常量,意味着指针指向的位置不可变,但是指针指向位置的值可变。即:

// 这两者的语句是等效的,因此引用被当作指针常量来处理int& p_a = a;  int* const p_a=&a;

再补充一点小知识,关于 const 修饰符的问题,有些新手朋友来说很容易弄不清楚 const 修饰下什么是可变的,什么是不可变的。具体实例如下:

int data = 10, data2 = 20;const int* p_data = &data; //修饰的是int,即 p_data 所指向的值不可变,而p_data可变p_data = &data2;int* const p_data2 = &data; //修饰的是int*,即 p_data 所指向的值可变,而p_data不可变*p_data2 = data2;

引用即是第二种用法。

关于“C++中指针与引用的区别是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“C++中指针与引用的区别是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网其他教程频道。

--结束END--

本文标题: C++中指针与引用的区别是什么

本文链接: https://www.lsjlt.com/news/296200.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • c语言怎么计算字符串长度
    在C语言中,可以使用内置的strlen()函数来计算字符串的长度。该函数位于string.h头文件中。以下是一个示例代码: #inc...
    99+
    2024-05-14
    c语言
  • c语言怎么判断三个数的大小
    可以通过比较三个数之间的大小关系来判断它们的大小。以下是一个示例代码: #include <stdio.h> int ...
    99+
    2024-05-14
    c语言
  • c++排序函数sort怎么使用
    在C++中,使用sort函数对容器中的元素进行排序,可以按照默认的升序排列,也可以自定义排序规则。 下面是一个简单的例子,对一个ve...
    99+
    2024-05-14
    c++
  • c++中string的compare函数怎么使用
    在C++中,可以使用string的compare函数来比较两个string对象的大小。该函数的原型如下: int compare(c...
    99+
    2024-05-14
    c++
  • c++中string的compare函数有什么用
    c++中string的compare函数用于比较两个字符串的大小关系。该函数返回一个整数值,表示两个字符串的比较结果。 具体来说,如...
    99+
    2024-05-14
    c++
  • c++中print函数的功能有哪些
    在C++中,通常使用std::cout来进行输出操作,而不是使用print函数。std::cout是C++标准库中的一个输出流对象,...
    99+
    2024-05-14
    c++
  • c语言数据结构怎么使用
    在C语言中,数据结构可以通过定义结构体来实现。以下是一些常见的数据结构的使用方法示例: 链表: #include <std...
    99+
    2024-05-14
    c语言
  • c++中print函数的用法是什么
    在C++中没有内置的print函数,但可以使用cout来输出内容到控制台。cout是C++标准库中的一个输出流对象,可以使用<...
    99+
    2024-05-14
    c++
  • c++中concept的用法是什么
    在C++20中,Concept是一种新的语言特性,用于定义类型要求和约束。Concept可以被用来约束函数模板、类模板和普通函数的参...
    99+
    2024-05-14
    c++
  • c++中concept的作用是什么
    在C++中,concept的作用是定义一种通用的约束,用于限制模板参数的类型范围。通过使用concept,可以在编译时对模板参数进行...
    99+
    2024-05-14
    c++
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作