C++ 函数传指针和传引用与指针有什么区别的区别

当前位置:
> > 查看文章
传值、传值和传引用 – C++快速入门12
传值、传值和传引用
让编程改变世界
Change the world by program
传值、传址和传引用
这一节课我们对函数进行进一步的剖析讲解,希望给大家带来一些新鲜的感觉。
在编写个人函数的时候,你将受到C++中一条基本原则的限制:在默认的情况下,参数只能以值传递的方式给函数。
这句话的理解是:被传递到函数的只是变量的值,永远不会是变量本身。
例题:example.cpp()
请把地址给我
绕开“值传递”问题的第一种方法是向函数传递变量的地址取代它的值。我们说C语言强大,有很大一部分就是在于他的灵活,他的灵活,有大一部
分就是可以利用指针进行委婉地乱改。。。
正如我们所理解的,想要获取某个变量的地址只需要在它前边加上一个“取地址”操作符(&)就行了。
那我们可以试着这样:changeAge( &age, age+1 )
试试看:example.cpp()
注意:如果传过去的是地址,在函数中必须要通过“*”对指针进行解引用,除非你有其他用途。
练习:swap.cpp()
另外的一种不需要中介的互换方案:swap2.cpp()
传址在我们看来已经是很不错,不过C++语言的大神们在完善的过程中完善了地址这个概念。
设想:如果事先就知道某个函数的参数只能接受一个地址,能不能使用某种约定使得在调用该函数时不需要使用指针的语法呢?
于是乎,以引用传递方式传递输入方式的概念因此而产生了。
其实他跟我们这个传址的目的是一样的,都是把地址传递给函数,但语法不同更加容易使用了。
反汇编对比三种传递方式分析讲解运行原理。。。(具体内容请看视频中详细讲解)
小甲鱼在干啥
如果您觉得小甲鱼的视频能够给您带来知识和快乐,您可以选择赞助我们,让我们可以持续为您推出更多精彩的原创编程教学^_^
手机用户打开支付宝钱包,扫描下方支付宝二维码即可:
电脑用户点击下方按钮即可跳转至支付宝转账页面:
感谢您对我们发展的支持和认可!
更多新鲜事儿
加载中……温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
冰封心跳...
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(4272)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'C++传引用与传指针的效率比较',
blogAbstract:'&\r\n  记得初学C++时看过某书说“引用”在C++中是不占任何空间的,所以效率比指针高,当时看书就觉得奇怪,比32机的4字节地址空间还小?我一直始终认为指针在编译为要机器代码在32机上是一样的4字节地址,去年和以前的一个同事谈起此事,同事也抱着相同的观点,我也没办法说服他,只有用一段程序来验证结果。\r\n// RefAndPointerTest.cpp : 定义控制台应用程序的入口点。//\r\n#include \"stdafx.h\"#include \"iostream\"#include \"windows.h\"//#include \"winbase.h\"\r\n',
blogTag:'编程',
blogUrl:'blog/static/1012092',
isPublished:1,
istop:false,
modifyTime:6,
publishTime:2,
permalink:'blog/static/1012092',
commentCount:2,
mainCommentCount:2,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'冰封心跳...',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}C++引用&和指针在作为形参时的区别
在C++中,多了一个C语言没有的引用声明符&,如上,m就是n的引用,简单的说m就是n的别名,两者在内存中占同样的位置,不对m开辟新的内存空间,对m的任何操作,对n来说是一样的。
对于引用,有以下三条规则:
(1)引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。
(2)不能有NULL 引用,引用必须与合法的存储单元关联(指针则可以是NULL)。
(3)一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。
指针和引用的区别:
(1)指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。
(2)可以有const指针,但是没有const引用;
(3)指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)
(4)指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化;
(5)指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了。
(6)"sizeof引用"得到的是所指向的变量(对象)的大小,而"sizeof指针"得到的是指针本身的大小;
(7)指针和引用的自增(++)运算意义不一样;
在讲引用作为函数参数进行传递时,实质上传递的是实参本身,即传递进来的不是实参的一个拷贝,因此对形参的修改其实是对实参的修改,所以在用引用进行参数传递时,不仅节约时间,而且可以节约空间。
假如在一个函数中动态申请内存空间,用指针和用引用作形参会得到不同的结果,如下面的例子:
void fun(int* b){
//用指针做形参
b = (int*)malloc(sizeof(int)*3);
for(int i=0; i<3; i&#43;&#43;){
void fun(int* &b){
//用引用做形参
b = (int*)malloc(sizeof(int)*3);
for(int i=0; i<3; i&#43;&#43;){
如果在main函数中定义了一个int型的空指针并分别作为实参传入,如下:
int main(){
int *a = NULL;
for(int i=0; i<3; i&#43;&#43;){
cout << a[i] << " ";
cout << "\n";
结果用指针的函数会出现内存访问出错,用引用的函数则运行正常并正确输出1 2 3.
这是因为:
1.指针虽然是地址传递,但实际上也是在函数中又定义了一个新的指针让其与传入的指针指向同一地址。但两个指针本身作为变量在内存中的存放地址是不同的,就是说这是两个不同的变量,只是内容(即所指地址)相同。
2.在函数中对新定义的指针动态申请内存,但是当函数结束后,申请的内存的生命周期也就结束了,所以当回到主函数时,作为实参的指针地址和内容都没有变化。仍然是个空指针,对其进行访问自然出现了内存读错误了。
假如在main函数中这样写:
int *a = (int*)malloc(sizeof(int)*3);
就不会出现内存读错误了,但是输出结果还是错误的,道理也是一样的。
3.用引用作为实参传入时,fun函数中的b其实就是主函数中a的别名(或者叫外号),反正就是操作完全相同,地址相同,内容相同的一个变量,所以当fun函数返回时,对b的操作在主函数中对a同样有效。
再看一个例子:
int *a = NULL;
char* b = (char*)a;
int *a = NULL;
char* &b = (char*)a;
这一次是在编译阶段的区别:
用指针可以通过编译,而用引用则不可以,提示类型转换出错。
通过这两个例子可以看出,指针比引用灵活,也更加危险。
摘自『高质量c++』
条款一:指针与引用的区别
指针与引用看上去完全不同(指针用操作符’*’和’->’,引用使用操作符’.’),但是它们&#20284;乎有相同的功能。指针与引用都是让你间接引用其他对象。你如何决定在什么时候使用指针,在什么时候使用引用呢?
首先,要认识到在任何情况下都不能用指向空&#20540;的引用。一个引用必须总是指向某些对象。因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空&#20540;给该变量。相反,如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。
PS:引用在定义时不可加const,否则编译出错,在形参前面则可以加const以确保在函数中该变量不会被修改。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'C++函数参数和返回值三种传递方式:值传递、指针传递和引用传递(着重理解)_C++,C语言_ThinkSAAS
C++函数参数和返回值三种传递方式:值传递、指针传递和引用传递(着重理解)
C++函数参数和返回值三种传递方式:值传递、指针传递和引用传递(着重理解)
C++函数参数和返回值三种传递方式:值传递、指针传递和引用传递(着重理解)
引用与指针的比较
引用是 C++中的概念,初学者容易把引用和指针混淆一起。一下程序中,n 是m 的
一个引用(reference),m 是被引用物(referent)。
n 相当于m 的别名(绰号),对n 的任何操作就是对m 的操作。例如有人名叫王小毛,
他的绰号是“三毛”。说“三毛”怎么怎么的,其实就是对王小毛说三道四。所以n 既
不是m 的拷贝,也不是指向m 的指针,其实n 就是m 它自己。
引用的一些规则如下:
(1)引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。
(2)不能有NULL 引用,引用必须与合法的存储单元关联(指针则可以是NULL)。
(3)一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。
以下示例程序中,k 被初始化为i 的引用。语句k = j 并不能将k 修改成为j 的引
用,只是把k 的值改变成为6。由于k 是i 的引用,所以i 的值也变成了6。
int i = 5;
int j = 6;
k = // k 和i 的值都变成了6;
上面的程序看起来象在玩文字游戏,没有体现出引用的价值。引用的主要功能是传
递函数的参数和返回值。C++语言中,函数的参数和返回值的传递方式有三种:值传递、
指针传递和引用传递。
以下是“值传递”的示例程序。由于Func1 函数体内的x 是外部变量n 的一份拷贝,
改变x 的值不会影响n, 所以n 的值仍然是0。
void Func1(int x)
x = x + 10;
int n = 0;
cout && “n = ” && n && // n = 0
以下是“指针传递”的示例程序。由于Func2 函数体内的x 是指向外部变量n 的指
针,改变该指针的内容将导致n的值改变,所以n 的值成为10。
void Func2(int *x)
(* x) = (* x) + 10;
int n = 0;
Func2(&n);
cout && “n = ” && n && // n = 10
以下是“引用传递”的示例程序。由于Func3 函数体内的x 是外部变量n 的引用,
x 和n 是同一个东西,改变x 等于改变n,所以n 的值成为10。
void Func3(int &x)
x = x + 10;
int n = 0;
cout && “n = ” && n && // n = 10
对比上述三个示例程序,会发现“引用传递”的性质象“指针传递”,而书写方式
象“值传递”。实际上“引用”可以做的任何事情“指针”也都能够做,为什么还要“引
用”这东西?
答案是“用适当的工具做恰如其分的工作”。
指针能够毫无约束地操作内存中的如何东西,尽管指针功能强大,但是非常危险。
就象一把刀,它可以用来砍树、裁纸、修指甲、理发等等,谁敢这样用?
如果的确只需要借用一下某个对象的“别名”,那么就用“引用”,而不要用“指针”,
以免发生意外。
摘自 THISISPAN的专栏
PHP开发框架
开发工具/编程工具
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
让ThinkSAAS更好,把建议拿来。
开发客服微信

我要回帖

更多关于 引用和指针的区别 的文章

 

随机推荐