什么时候该用指针 什么时候该用引用

九度空间 2010-06-29 10:50:00
什么时候该用指针 什么时候该用引用 头疼死我了 请大家们举个例子说明一下 感激不尽
...全文
1643 57 打赏 收藏 转发到动态 举报
写回复
用AI写文章
57 条回复
切换为时间正序
请发表友善的回复…
发表回复
hsc456 2012-05-19
  • 打赏
  • 举报
回复
都是地址的概念:

  指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

不同点:
  1.指针是一个实体,而引用仅是个别名;

  2.引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;
  3.引用没有const,指针有const,const的指针不可变;
  4.引用不能为空,指针可以为空;
  5.“sizeof引用”得到的是所指向的变量(对象)的大小,而“sizeof指针”得到的是指针本身的大小;
  6.指针和引用的自增(++)运算意义不一样;
  7.引用是类型安全的,而指针不是(引用比指针多了类型检查)


  根据上面的规则,优先考虑用引用,不能用引用的情况下用指针.
子曰过 2012-02-28
  • 打赏
  • 举报
回复
指针和引用是有区别,但实际用起来,功能基本一样,有多少人会把传进来的指针重新赋值
我也想知道何时该用哪个,写代码时,一样用下,感觉好不规范。整篇帖子看完后。。。貌似还没个结论
hy_67 2011-02-21
  • 打赏
  • 举报
回复
37# 1+
  • 打赏
  • 举报
回复
就函数参数而言,引用与指针相比也就是对调用者来说方便一些罢了。

一般有这样几条“潜规则”:
◇ 如果参数是个支持多态的类指针,必须用指针。
◇ 简单类型能作为返回值的尽量作为返回值,而不要作为引用型参数。
◇ 指针比引用的适应性更好,比如:

int Func1(int* pn)
{
...
}

int Func2(int& pn)
{
...
}

...

{
long n = 0;
Func1((int*)&n);
Func2((int&)*(int*)&n); // 很麻烦,是吧
}

风中的过客A 2010-06-29
  • 打赏
  • 举报
回复
总的来说,在以下情况下应该使用指针:一是你考虑到存在不指向任何对象的可能(在这种情况下,你能够设置指针为NULL),二是你需要能够在不同的时刻指向不同的对象(在这种情况下,你能改变指针的指向)。如果总是指向一个对象并且一旦指向一个对象后就不会改变指向,那么你应该使用引用。
山书生 2010-06-29
  • 打赏
  • 举报
回复
最近也在琢磨这个问题,面临问题,好材…… :)
we_sky2008 2010-06-29
  • 打赏
  • 举报
回复
<<more effective c++>>
3.1 Item M1:指针与引用的区别


指针与引用看上去完全不同(指针用操作符“*”和“->”,引用使用操作符“. ”),但是它们似乎有相同的功能。指针与引用都是让你间接引用其他对象。你如何决定在什么时候使用指针,在什么时候使用引用呢?

首先,要认识到在任何情况下都不能使用指向空值的引用。一个引用必须总是指向某些对象。因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量。相反,如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。

“但是,请等一下”,你怀疑地问,“这样的代码会产生什么样的后果?”

char *pc = 0; // 设置指针为空值

char& rc = *pc; // 让引用指向空值

这是非常有害的,毫无疑问。结果将是不确定的(编译器能产生一些输出,导致任何事情都有可能发生)。应该躲开写出这样代码的人,除非他们同意改正错误。如果你担心这样的代码会出现在你的软件里,那么你最好完全避免使用引用,要不然就去让更优秀的程序员去做。我们以后将忽略一个引用指向空值的可能性。

因为引用肯定会指向一个对象,在C++里,引用应被初始化。

string& rs; // 错误,引用必须被初始化

string s("xyzzy");

string& rs = s; // 正确,rs指向s

指针没有这样的限制。

string *ps; // 未初始化的指针

// 合法但危险

不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。

void printDouble(const double& rd)

{

cout << rd; // 不需要测试rd,它

} // 肯定指向一个double值

相反,指针则应该总是被测试,防止其为空:

void printDouble(const double *pd)

{

if (pd) { // 检查是否为NULL

cout << *pd;

}

}

指针与引用的另一个重要的不同是指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象,以后不能改变。

string s1("Nancy");

string s2("Clancy");

string& rs = s1; // rs 引用 s1

string *ps = &s1; // ps 指向 s1

rs = s2; // rs 仍旧引用s1,

// 但是 s1的值现在是

// "Clancy"

ps = &s2; // ps 现在指向 s2;

// s1 没有改变

总的来说,在以下情况下你应该使用指针,一是你考虑到存在不指向任何对象的可能(在这种情况下,你能够设置指针为空),二是你需要能够在不同的时刻指向不同的对象(在这种情况下,你能改变指针的指向)。如果总是指向一个对象并且一旦指向一个对象后就不会改变指向,那么你应该使用引用。

还有一种情况,就是当你重载某个操作符时,你应该使用引用。最普通的例子是操作符[]。这个操作符典型的用法是返回一个目标对象,其能被赋值。

vector<int> v(10); // 建立整形向量(vector),大小为10;

// 向量是一个在标准C库中的一个模板(见条款M35)

v[5] = 10; // 这个被赋值的目标对象就是操作符[]返回的值

如果操作符[]返回一个指针,那么后一个语句就得这样写:

*v[5] = 10;

但是这样会使得v看上去象是一个向量指针。因此你会选择让操作符返回一个引用。(这有一个有趣的例外,参见条款M30)

当你知道你必须指向一个对象并且不想改变其指向时,或者在重载操作符并为防止不必要的语义误解时,你不应该使用指针。而在除此之外的其他情况下,则应使用指针。
温暖阳光236 2010-06-29
  • 打赏
  • 举报
回复
我来学习一下可以吧?
yanran_hill 2010-06-29
  • 打赏
  • 举报
回复
俺只了解几个例子,思路很窄,就当抛个砖吧:
在operator <<,>>等流操作符,是要使用引用的,其它的,象拷贝构造函数,赋植操作也是使用引用的
在单件模式,或者设计工厂类里面,有时候需要在堆上创建实例,不允许在栈上创建实例,或者需要使用内存块作为操作缓冲区/队列的时候,就要使用指针
ForestDB 2010-06-29
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 xxlovemf 的回复:]
引用 1 楼 zhaolinger2 的回复:
你明白指针和引用是什么意思了吗?

概念很清楚 就是很糊涂
[/Quote]
LZ这么说,就是还是糊涂中,起码可以说有点模糊。
这种东西,重在理解/实践,我是通过自己写各种代码以及debug工具来理解的,当然这需要一些计算机组成这些基础的知识(即要从底层去思考上层的抽象)。
九度空间 2010-06-29
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 ajysnihao 的回复:]
我不是来回答你的问题的,来拿可用分
[/Quote]
那你可以去死了
ajysnihao 2010-06-29
  • 打赏
  • 举报
回复
我不是来回答你的问题的,来拿可用分
九度空间 2010-06-29
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 xt0601 的回复:]
想很好的用指针和引用很难;但你可以只知道他们的其中一种用法并熟练的运行他们!
简单的说一下我的理解:指针可以快速的访问和控制从而得到你想要的,但是他会给你带来麻烦;引用,其实他就是一个拷贝(他拷贝他的引用对象),只要他的拷贝对象存在,则他就是他永远等于他的拷贝对象,并且他跟随他的拷贝对像一起在变。
指针和引用在对数组时他们有一定的不同:
指针在指向数组时,他得到的只是数组的首地址(即 数组名……
[/Quote]
有一点道理
九度空间 2010-06-29
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 cao_julians 的回复:]
尽可能先考虑简捷地使用“引用”,不行的时候(不能用“引用”或引用方式不简捷)再“考虑”指针。
[/Quote]
那为什么很多函数(包括mfc中)大多用到指针
你怎么解释???
九度空间 2010-06-29
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 yuwenge 的回复:]
指针是说,我这里有个变量的首地址。变量是不是存在我不管。
引用是说,这里有一个变量,内存分配好了,不能改,你来用吧。
[/Quote]
通俗易懂 很不错
djjlove_2008 2010-06-29
  • 打赏
  • 举报
回复
不用那么复杂,专家建议:尽量使用引用,专家们把引用定义为安全而高效的指针,他们在二进制层面是一样的,想想C++为什么会加个引用机制,相信引用的好处不用说大家也知道了吧,呵呵。加油。
其指针和引用还有很多细微的区别,建议楼主去百度下。
xt0601 2010-06-29
  • 打赏
  • 举报
回复
想很好的用指针和引用很难;但你可以只知道他们的其中一种用法并熟练的运行他们!
简单的说一下我的理解:指针可以快速的访问和控制从而得到你想要的,但是他会给你带来麻烦;引用,其实他就是一个拷贝(他拷贝他的引用对象),只要他的拷贝对象存在,则他就是他永远等于他的拷贝对象,并且他跟随他的拷贝对像一起在变。
指针和引用在对数组时他们有一定的不同:
指针在指向数组时,他得到的只是数组的首地址(即 数组名[0],其值就是数组名[0]的值),要得到整个数据的所有值,需要 (*P)++ ;而引用数组名也只是得到数组首地址里的值,要得到整个数据的所有值,需要&(数组名)++ ,他得到的是数据的下标.
caizhihong 2010-06-29
  • 打赏
  • 举报
回复
指针就是一个内存地址,而引用即可充当指针的作用,也可以充当变量的作用
304的的哥 2010-06-29
  • 打赏
  • 举报
回复
C语言的精华和灵魂是“指针”,但运用的时候却比较容易出错。c++又引入了“引用”的概念,好多人不理解它们之间的区别,本人将结合自己的使用经验,给出一些编程的实例,简单阐述它们之间的区别。

一。普通变量的存储方式

在没介绍指针之前,我们先看一下普通变量在系统中的存储方式。看如下程序。

void main( void )

{

int ia = 12;

int ib = 45;

cout << "&ia : " << &ia << " , ia : " << ia << endl;

cout << "&ib : " << &ib << " , ib : " << ib << endl;

return;

}

在程序中定义ia、ib两个变量后,系统将在内存地址中分配两个地址空间用于存放变量。地址里的内容就是变量的值, 程序的执行结果如下: (注意:下面的地址是随机的,可能会跟读者的结果不同)

&ia : 0x0012FF7C , ia : 12

&ib : 0x0012FF78 , ib : 45

可见: ia对应的内存地址为:0x0012FF7C,而这个地址里的内容是12

ib对应的内存地址为:0x0012FF78,而这个地址里的内容是45

普通变量,在它所分配的地址空间里面的内容就是它的值。

二。指针变量的存储方式

编译执行

void main( void )

{

int ia = 12;

int ib = 45;

cout << "&ia : " << &ia << " , ia : " << ia << endl;

cout << "&ib : " << &ib << " , ib : " << ib << endl;

int *ip1, *ip2;

ip1 = &ia;

ip2 = &ib;

cout << "&ip1:" << &ip1 << " , ip1:" << ip1 << " , *ip1:" << *ip1 << endl;

cout << "&ip2:" << &ip2 << " , ip2:" << ip2 << " , *ip1:" << *ip1 << endl;

}

我们定义了两个指向整数类型的指针ip1、ip2,让它们分别指向ia和ib,输出它们各自在内存中的地址,指针的值,和指针所指向的地址里面的值。程序的执行结果如下:

&ia : 0x0012FF7C , ia : 12

&ib : 0x0012FF78 , ib : 45

&ip1:0x0012FF74 , ip1:0x0012FF7C , *ip1:12

&ip2:0x0012FF70 , ip2:0x0012FF78 , *ip1:12

我们发现ip1和ip2的地址和ia、ib不同,这说明指针变量和其他的变量一样,都有自己独立的地址空间。而指针的值恰好是一个地址,这个地址就是ia和ib变量的地址。地址里的值就是ia和ib的值。这一下我们明白了。

原来:指针变量和其他的变量一样,都有自己独立的地址空间,它里面的值不是真正的值,而是一个地址,系统通过这个地址,才能找到真正需要的值,是一种间接的寻址方式。

三。引用变量的存储方式。

编译执行 下面代码

void main( void )

{

int ia = 12;

int ib = 45;

cout << "&ia : " << &ia << " , ia : " << ia << endl;

cout << "&ib : " << &ib << " , ib : " << ib << endl;

int &iy1 = ia;

int &iy2 = ib;

cout << "&iy1 : " << &iy1 << " , iy1 : " << iy1 << endl;

cout << "&iy2 : " << &iy2 << " , iy2 : " << iy2 << endl;

}

我们定义了两个整数类型的引用变量iy1、iy2,分别声明为ia、ib的引用。输出结果

&ia : 0x0012FF7C , ia : 12

&ib : 0x0012FF78 , ib : 45

&iy1 : 0x0012FF7C , iy1 : 12

&iy2 : 0x0012FF78 , iy2 : 45

我们发现iy1、iy的地址与ia、ib完全相同,且值也相等。可见系统并没有为iy1和iy2分配单独的地址空间,iy1和iy2只是作为ia和ib的别名,这就是引用的存储机制。

通过以上所举的编程实例,读者应该基本掌握了这三者之间的关系和区别。 下面举实例看一看这三种方式,作为i函数参数的区别和注意事项。

四。参数为普通值参数

看下面的程序,编译并执行

void input(int a, int b)

{

cout << "-------------function input()----------" << endl;

cout << "&a : " << &a << " , a : " << a << endl;

cout << "&b : " << &b << " , b : " << b << endl;

a = 44;

b = 55;

cout << "&a : " << &a << " , a : " << a << endl;
cout << "&b : " << &b << " , b : " << b << endl;

}

int main(void)

{

int ia = 11;

int ib = 22;

cout << "-------------main()--------------------" << endl;

cout << "&ia : " << &ia << " , ia : " << ia << endl;

cout << "&ib : " << &ib << " , ib : " << ib << endl;

input(ia,ib);

cout << "-------------main()--------------------" << endl;

cout << "&ia : " << &ia << " , ia : " << ia << endl;

cout << "&ib : " << &ib << " , ib : " << ib << endl;

return 1;

}

输出结果:

--------------main()--------------------

&ia : 0x0012FF7C , ia : 11

&ib : 0x0012FF78 , ib : 22

-------------function input()----------

&a : 0x0012FF24 , a : 11

&b : 0x0012FF28 , b : 22

&a : 0x0012FF24 , a : 44

&b : 0x0012FF28 , b : 55

--------------main()--------------------

&ia : 0x0012FF7C , ia : 11

&ib : 0x0012FF78 , ib : 22

我们看到,主程序中的ia、ib的地址和函数input()中a、b的地址不同,也就是说:a、b是系统在发生函数调用时生成的临时变量,虽然值和ia、ib相同,但却是两个不同地址空间的变量。和主程序中的变量是完全独立的。在函数中我们看到临时变量a、b的值确实改变了,但当返回主程序时,ia、ib的值并没有改变。原因就是,你改变的只是函数内部的局部变量a、b的值,并没有改变主程序中ia、ib的值,并且当函数结束时,临时变量a、b也销毁了。主程序的值,没发生改变。

五。参数为指针参数

输入下面程序,编译并执行

void input(int *a, int *b)

{

cout << "-------------input()----------" << endl; 、

cout << "&a : " << &a << " , a : " << a << " , *a : " << *a << endl;

cout << "&b : " << &b << " , b : " << b << " , *b : " << *b << endl;

*a = 44;

*b = 55;

cout << "&a : " << &a << " , a : " << a << " , *a : " << *a << endl;

cout << "&b : " << &b << " , b : " << b << " , *b : " << *b << endl;

}

int main()

{

int ia = 11;

int ib = 22;

cout << "-------------in main()--------------------" << endl;

cout << "&ia : " << &ia << " , ia : " << ia << endl;

cout << "&ib : " << &ib << " , ib : " << ib << endl;

input(&ia,&ib);

cout << "-------------in main()--------------------" << endl;

cout << "&ia : " << &ia << " , ia : " << ia << endl;

cout << "&ib : " << &ib << " , ib : " << ib << endl;

return 1;

}

输出结果:

-------------in main()--------------------

&ia : 0x0012FF7C , ia : 11

&ib : 0x0012FF78 , ib : 22

-------------input()----------

&a : 0x0012FF24 , a : 0x0012FF7C , *a : 11

&b : 0x0012FF28 , b : 0x0012FF78 , *b : 22

&a : 0x0012FF24 , a : 0x0012FF7C , *a : 44

&b : 0x0012FF28 , b : 0x0012FF78 , *b : 55

-------------in main()--------------------

&ia : 0x0012FF7C , ia : 44

&ib : 0x0012FF78 , ib : 55

我们看到,主程序中的ia、ib的地址和函数input()中a、b的地址不同,说明a、b是系统在发生函数调用时生成的临时变量。和普通的变量一样,指针类型的变量也有自己的地址空间。但a和b的值正是ia和ib的地址。所以我们通过直接改变地址里的值,在函数内部修改了主程序中变量。从输出结果上我们看到,主程序的值改变了。

六。参数为引用参数

输入下面程序,编译并执行

void input(int &a, int &b)

{

cout << "-------------input()----------" << endl;

cout << "&a : " << &a << " , a : " << a << endl;

cout << "&b : " << &b << " , b : " << b << endl; a = 44; b = 55;

cout << "&a : " << &a << " , a : " << a << endl;

cout << "&b : " << &b << " , b : " << b << endl;

}

int main(int argc, char* argv[])

{

int ia = 11;

int ib = 22;

cout << "-------------in main()--------------------" << endl;

cout << "&ia : " << &ia << " , ia : " << ia << endl;

cout << "&ib : " << &ib << " , ib : " << ib << endl;

input(ia,ib);

cout << "-------------in main()--------------------" << endl;

cout << "&ia : " << &ia << " , ia : " << ia << endl;

cout << "&ib : " << &ib << " , ib : " << ib << endl;

return 1;

}

输出结果:

-------------in main()--------------------

&ia : 0x0012FF7C , ia : 11

&ib : 0x0012FF78 , ib : 22

-------------input()----------

&a : 0x0012FF7C , a : 11

&b : 0x0012FF78 , b : 22

&a : 0x0012FF7C , a : 44

&b : 0x0012FF78 , b : 55

-------------in main()--------------------

&ia : 0x0012FF7C , ia : 44

&ib : 0x0012FF78 , ib : 55

我们看到,函数中a、b的地址和主程序中的ia、ib完全相同,就是说:在引用方式的参数传递中,系统并没有生成临时变量,没有分配独立的地址空间,而是直接将变量本身传递给了函数,并且在函数内部对变量所做的修改,可直接作用到主程序中。

总结:

在值传递和指针传递的参数传递方式中,系统都生成了临时的局部变量,值传递方式中,在函数内部无法修改实际参数的值,只能修改临时参数的值。在指针传递的参数传递方式中,是通过直接修改实际参数地址里的值的方法,达到了修改值的目的。运用的是间接的寻址方式。而在引用传递的参数传递方式中,因为参数就是实际参数本身,所以我们对参数的修改,将直接反映给主程序。

希望我的一点经验,能给大家一些帮助。所有程序在winxp,vc6.0下调试通过。

cao_julians 2010-06-29
  • 打赏
  • 举报
回复
尽可能先考虑简捷地使用“引用”,不行的时候(不能用“引用”或引用方式不简捷)再“考虑”指针。
加载更多回复(36)

64,685

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧