Chinaunix

标题: 你们的代码会用引用吗? [打印本页]

作者: lipingtababa    时间: 2008-11-18 17:14
标题: 你们的代码会用引用吗?
我学习C++的时候,已经学习了C,对C的指针有些基本可用的理解,其程度相当于可以使用指针写代码,但不是很理解函数的参数传递机理.

那时候怎么也不明白为什么C++要引入引用,我坚持认为引用肯定有独特之处,之所以引入它,肯定是因为指针不够强大.

后来写多了代码,我觉得这个玩意的引入完全是多余的,他所有的功能都可以被指针取代(实际上它也是用指针实现的).

比如最常用的 void fun(const Type& para)就可以用 void fun(const Type* p_para)取代.

我还见过类似 void fun(Type* & p)的代码,真是难看啊, void fun(Type ** pp)直接明了多了.
作者: flw    时间: 2008-11-18 17:34
你先别学引用,然后用指针,等吃上几次亏,就会想办法去解决了,那时候你就会明白,你想要的其实不是指针,而是引用。

凡事得讲究火候,有些人一学引用,就明白它的好了。
你不明白,那就不要强求,等你需要它的时候,你自然就明白了。
作者: lipingtababa    时间: 2008-11-18 17:36
请举例,请举例.

我举的例子里,都是指针比引用方便而且至关
作者: cugb_cat    时间: 2008-11-18 17:38
原帖由 flw 于 2008-11-18 17:34 发表
你先别学引用,然后用指针,等吃上几次亏,就会想办法去解决了,那时候你就会明白,你想要的其实不是指针,而是引用。

凡事得讲究火候,有些人一学引用,就明白它的好了。
你不明白,那就不要强求,等你需要 ...

恩,认真的学了C++,才知道引用太好用了。。
作者: lipingtababa    时间: 2008-11-18 17:40
太好用了,太好用了,太好用了..........................

这样说一百遍,别人也看不出来好用在哪里.
作者: net_robber    时间: 2008-11-18 17:53
原帖由 cugb_cat 于 2008-11-18 17:38 发表

恩,认真的学了C++,才知道引用太好用了。。

到底是面向对象好用还是C++ 好用??


我觉得C++ 不一定好用,但是面向对象还是很不错的
作者: cugb_cat    时间: 2008-11-18 17:58
原帖由 net_robber 于 2008-11-18 17:53 发表

到底是面向对象好用还是C++ 好用??


我觉得C++ 不一定好用,但是面向对象还是很不错的

这个我没发言权,我的水平还差很多。
作者: fera    时间: 2008-11-18 17:58
原帖由 flw 于 2008-11-18 17:34 发表
你先别学引用,然后用指针,等吃上几次亏,就会想办法去解决了,那时候你就会明白,你想要的其实不是指针,而是引用。

凡事得讲究火候,有些人一学引用,就明白它的好了。
你不明白,那就不要强求,等你需要 ...

嗯~
指针很邪恶的……
光从传参上看指针和引用看不出引用的好。
作者: flw    时间: 2008-11-18 18:05
原帖由 lipingtababa 于 2008-11-18 17:40 发表
太好用了,太好用了,太好用了..........................

这样说一百遍,别人也看不出来好用在哪里.

没明白就没明白呗。说明火候还不到,慢慢来,别着急。
作者: flw    时间: 2008-11-18 18:06
原帖由 lipingtababa 于 2008-11-18 17:36 发表
请举例,请举例.

我举的例子里,都是指针比引用方便而且至关

那你就继续用指针呗。
引用这东西本来就是用在指针不好用的情况下的,
既然你觉得指针很好用,那你就继续用指针呗。
作者: lipingtababa    时间: 2008-11-18 18:08
哎,你宁愿回两个帖鼓励我慢慢来,就是不肯举一个例.

建议版规增加一条:代码是王道!
作者: flw    时间: 2008-11-18 18:10
原帖由 lipingtababa 于 2008-11-18 18:08 发表
哎,你宁愿回两个帖鼓励我慢慢来,就是不肯举一个例.

建议版规增加一条:代码是王道!


我觉得还是慢慢积累吧。

[ 本帖最后由 flw 于 2008-11-18 18:13 编辑 ]
作者: Godbach    时间: 2008-11-18 18:13
原帖由 flw 于 2008-11-18 18:10 发表


不是我不肯举例,而是我实在对你没信心。
我不相信我在百忙之中匆匆举几个例子你就突然能明白了。
我觉得还是慢慢积累吧。


有些技巧的使用是靠慢慢积累的
作者: gawk    时间: 2008-11-18 18:14
进来学习
作者: arust    时间: 2008-11-18 18:14
我也是刚学 C++,感觉引用比指针更加安全
作者: flw    时间: 2008-11-18 18:15
这么说吧,
除了 C 语言,没几种语言有指针这种东西。
不过大多数语言都有引用。
作者: lipingtababa    时间: 2008-11-18 18:15
一个天天在论坛灌水的人,还自称"百忙之中", 我真的要
作者: flw    时间: 2008-11-18 18:17
原帖由 lipingtababa 于 2008-11-18 18:15 发表
一个天天在论坛灌水的人,还自称"百忙之中", 我真的要

灌水也是工作啊。
有的水必须得灌,
有的水就不那么有意义了。
作者: CMAX    时间: 2008-11-18 18:17
引用可以用的很放肆
这是我的一点点感觉,不过c++写的少,没啥话语权
作者: lipingtababa    时间: 2008-11-18 18:22
算了,不较劲了.
作者: alexhappy    时间: 2008-11-18 18:22
算了,搞这么复杂做什么?
引用的目的就是用不着指针
作者: lipingtababa    时间: 2008-11-18 18:24
引用不可能取代指针啊, new出来的就是指针
作者: flw    时间: 2008-11-18 18:27
原帖由 lipingtababa 于 2008-11-18 18:24 发表
引用不可能取代指针啊, new出来的就是指针

那就连 new 也一起不要喽。
作者: nhuczp    时间: 2008-11-18 18:36
好与不好,等你用了就知道!!
这东西还是要多实践!!

如果想学可以多看看文件系统的部分的代码。
作者: yangsf5    时间: 2008-11-18 19:51
c++ primer
中文版第4版,第202页。

中间小提示:从c语言背景转到c++的程序员习惯通过传递指针来实现对实参的访问。在c++中,使用引用形参则更安全和更自然。
作者: billzhou    时间: 2008-11-18 20:44
引用和指针有些地方功能相似,大多地方可以用指针替换,但引用有时候却有很大的性能优势   
  稳定、速度、占用空间小..等   另外我感觉操作符重载是引用最重要的体现
作者: yhb04    时间: 2008-11-18 20:49
原帖由 billzhou 于 2008-11-18 20:44 发表
引用和指针有些地方功能相似,大多地方可以用指针替换,但引用有时候却有很大的性能优势   
  稳定、速度、占用空间小..等   另外我感觉操作符重载是引用最重要的体现

一看就知道没好好学过编译,什么叫“但引用有时候却有很大的性能优势 稳定、速度、占用空间小”?
这只是你的幻觉而已。在编译器层面引用跟指针几乎没有区别(除了别名分析引用有点优势),在编译器后端,引用就是一个固定值的指针。
不要人云亦云。
作者: 雨过白鹭洲    时间: 2008-11-18 20:53
我不用C++
作者: tyc611    时间: 2008-11-18 20:53
原帖由 billzhou 于 2008-11-18 20:44 发表
引用和指针有些地方功能相似,大多地方可以用指针替换,但引用有时候却有很大的性能优势   
  稳定、速度、占用空间小..等   另外我感觉操作符重载是引用最重要的体现

较之指针,引用何来性能优势之说?引用的底层实现跟指针是一回事
与指针相比较,引用的优点是更加安全和方便
作者: nubix    时间: 2008-11-18 21:16
呃,其实一样的啦,关键看使用者了.
难道引用就不能当指针来用了吗!!
作者: w_anthony    时间: 2008-11-18 21:21
估计说引用比指针好n多的,指针可以被引用取代的,大多都是写惯了高级语言的人。
从实现上讲,引用和指针原本就是一回事。
有人说一些引用无法被指针取代,比如拷贝构造函数云云,其实只要编译器支持,又怎么会取代不了?
有人说引用比指针安全,比如void func(int& p),p不会是空指针,但是如果别人要这么调用func(*(int*)NULL),两者又回到同一起跑线,其实安不安全主要取决于作者。
那么又为什么要搞个引用出来?
个人估计,一是因为写Variable.elem比写lpVariable->elem要快,二是将一个函数分割为多个函数时一些相关变量不需要修改为指针的形式。
说白了,就是为懒人服务的……

256色位图信息头,不想使用指针和new的写法:

  1. char buffer[sizeof(BITMAPINFOHEADER] + sizeof(RGBQUAD) * 256];
  2. BITMAPINFO& bih = *(BITMAPINFO*)buffer;
  3. //bih.
复制代码

以上完全可以用指针替代,只不过这样看起来舒服一点,写起来稍微方便一些而已。
作者: wzcsoft    时间: 2008-11-18 21:22
楼主,我来给你你想要的答案,从二者的区别入手。
(1)非空区别。在任何情况下都不能使用指向空值的引用。一个引用必须总是指向某些对象。因此如果你使用一个变量并让他指向一个对象,但是该变量在某些时候也可能不指向任何对象,这是你应该把变量声明为指针,因为这样你可以赋予空值给该变量。相反,如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。不存在指向空值得引用这个事实意味着使用引用的代码效率比使用指针要高。
(2)合法性区别。在使用引用之前不需要测试它的合法性。相反,指针则应该总是被测试,防止其为空。
(3)可修改区别。指针与引用的另一个重要的不同是指针可以被重新赋值以指向另一个不同的对象。但是引用则是总是指向在初始化时被指定的对象,以后不能改变,但是指定的对象其内容可以改变。
(4)应用区别。总的来说,在以下情况下你应该使用指针:一是你考虑到存在不指向任何对象对象的可能(在这种情况下,你能够设置指针为空),二是你需要能够在不同的时刻指向不同的对象(在这种情况下,你能改变指针的指向)。如果总是指向一个对象并且一旦指向一个对象后就不会改变指向,那么你应该使用引用。

技术肯定是要慢慢积累的,但有时候指引也是很必要的,我说的对吗,前面的高手们
作者: wzcsoft    时间: 2008-11-18 21:25
31楼说引用是为懒人服务,我是比较同意的,不过我的原则是能懒就懒
作者: w_anthony    时间: 2008-11-18 21:42
32L的(1)和(2):

  1. void func(int& p)
  2. {
  3.        //if (&p != NULL)
  4.             printf("%d",  p);
  5. }
  6. int main(int, char**)
  7. {
  8.      func(*(int*)NULL);
  9. }
复制代码

此时p是一个指向NULL的引用,加上判断程序正常,否则挂掉。
当然没人会傻到这么写,这就跟在void func(int* p /*Can not be NULL*/)这样的注释下,别人还要传NULL做参数,却抱怨指针不好用一样可笑。

(3):

  1. class U
  2. {
  3. public:
  4.         U(int u) : p(u) {};
  5. public:
  6.         union
  7.         {
  8.                 int& p;
  9.                 int* q;
  10.         };
  11. };

  12. int main(int, char**)
  13. {
  14.         int a = 0, b = 1;
  15.         U u(a);
  16.         printf("%d, ", u.p);
  17.         u.q = &b;
  18.         printf("%d\r\n", u.p);
  19.         return 0;
  20. }
复制代码

一次是0,另一次是1,U::p这个引用被指到了不同的地址。
作者: haohao06    时间: 2008-11-18 22:20
我喜欢引用,因为我讨厌指针的解引用。我觉得不好看。而且层数多了会让我晕
作者: whyglinux    时间: 2008-11-18 23:31
>> 那时候怎么也不明白为什么C++要引入引用,我坚持认为引用肯定有独特之处,之所以引入它,肯定是因为指针不够强大.

“引用肯定有独特之处”,这是肯定的;“之所以引入它,肯定是因为指针不够强大”,就不确切了。指针再强大,也有它照顾不到的地方;指针和引用也不是非此即彼的关系,它们有交叉,又有区别(自己独特的地方)。作为一个 C++ 程序员,要根据情况使用它们:有时用指针比较合适,有时非引用不可,有时又两者皆可用。

>> 后来写多了代码,我觉得这个玩意的引入完全是多余的,他所有的功能都可以被指针取代(实际上它也是用指针实现的).

参加下贴:
http://bbs.chinaunix.net/viewthr ... p;page=1#pid8249864

>> 比如最常用的 void fun(const Type& para)就可以用 void fun(const Type* p_para)取代.

不能完全取代。例如,对于前者可以这样调用 fun( Type() ),但是后者的调用要求实参必须是一个左值。

>> 我还见过类似 void fun(Type* & p)的代码,真是难看啊, void fun(Type ** pp)直接明了多了.

较之后者,我觉得前者的语义明确多了,不用象指针那样绕来绕去的。

>> 从实现上讲,引用和指针原本就是一回事。

不要人云亦云。引用和指针根本不是一回事,不论是语义上还是实现上。有这样的一个概念作为基础,更有助于你理解引用的本质。

>> 有人说一些引用无法被指针取代,比如拷贝构造函数云云,其实只要编译器支持,又怎么会取代不了?

基于值传递语义的对象拷贝构造函数事实上是实现不了的(或者说即使编译器允许这样的实现,也是不能被实际使用的),只能是基于引用语义的。

>> 有人说引用比指针安全,比如void func(int& p),p不会是空指针,但是如果别人要这么调用func(*(int*)NULL),两者又回到同一起跑线,其实安不安全主要取决于作者。

如果你不用指针的话,又何来 *(int*)NULL 这样的指针解引用的表达式呢?

当然,即使只用引用也可能会出现引用实际不存在的对象的情况,但是与指针比起来,这样的情况少多了。
作者: egmkang    时间: 2008-11-18 23:47
原帖由 flw 于 2008-11-18 18:10 发表


我觉得还是慢慢积累吧。


积累就积累.
呕吐算是什么
作者: egmkang    时间: 2008-11-18 23:53
让我看就一个糗样,有什么区别???
自己爱怎么用就怎么用
作者: selfrun    时间: 2008-11-19 00:16
#include <map>
using namespace std;
typedef map<int, int> _INT_MAP;
void f()
{
  _INT_MAP tmp_map;
  tmp_map[1] = 2;//有了引用就可以这样写
}
作者: w_anthony    时间: 2008-11-19 00:26
原帖由 whyglinux 于 2008-11-18 23:31 发表
>> 比如最常用的 void fun(const Type& para)就可以用 void fun(const Type* p_para)取代.

不能完全取代。例如,对于前者可以这样调用 fun( Type() ),但是后者的调用要求实参必须是一个左值。

>> 从实现上讲,引用和指针原本就是一回事。

不要人云亦云。引用和指针根本不是一回事,不论是语义上还是实现上。有这样的一个概念作为基础,更有助于你理解引用的本质。

>> 有人说一些引用无法被指针取代,比如拷贝构造函数云云,其实只要编译器支持,又怎么会取代不了?

基于值传递语义的对象拷贝构造函数事实上是实现不了的(或者说即使编译器允许这样的实现,也是不能被实际使用的),只能是基于引用语义的。

>> 有人说引用比指针安全,比如void func(int& p),p不会是空指针,但是如果别人要这么调用func(*(int*)NULL),两者又回到同一起跑线,其实安不安全主要取决于作者。

如果你不用指针的话,又何来 *(int*)NULL 这样的指针解引用的表达式呢?

当然,即使只用引用也可能会出现引用实际不存在的对象的情况,但是与指针比起来,这样的情况少多了。


1、VC编译器可以写fun(&Type())。
2、经验所致,非云云,union的例子很能说明两者到底是不是同一回事,对于存在编译优化而言,不管你是用引用还是指针, 编译的最终结果都是一样,指针也可能会被优化没掉,就像“别名”一样。
3、拷贝构造,这个你会错意了。只要编译器支持写成指针形式也当作拷贝构造,那么引用就被指针替代了,并不是指值传递。
4、这个你自己也说了可能会有不安全的情况,那我也不用多说了。本来安不安全主要就取决于作者的水平……
作者: emacsnw    时间: 2008-11-19 07:50
原帖由 lipingtababa 于 2008-11-18 01:14 发表
我学习C++的时候,已经学习了C,对C的指针有些基本可用的理解,其程度相当于可以使用指针写代码,但不是很理解函数的参数传递机理.

那时候怎么也不明白为什么C++要引入引用,我坚持认为引用肯定有独特之处,之所以 ...


楼主说的也不无道理。我基本上用引用的场合只限于 const Type &object。
不过这个和 const Type *object 还是有区别的: 引用的对象不必判断是否是 NULL ,直接可以用,比较方便。
作者: nicozhou    时间: 2008-11-19 08:40
原帖由 lipingtababa 于 2008-11-18 17:36 发表
请举例,请举例.

我举的例子里,都是指针比引用方便而且至关


这人很固执,FLW说的没错,你觉得指针比引用好用、方便,是因为你没有到时候,到火候。
作者: guoruimin    时间: 2008-11-19 08:49
原帖由 nicozhou 于 2008-11-19 08:40 发表


这人很固执,FLW说的没错,你觉得指针比引用好用、方便,是因为你没有到时候,到火候。

不要轻易的说别人不到火候!
或许还有人说认为引用好的不到火候呢!

我刚开始用的是C,后来大多数用C++(6年)。
现在写新东西都用C(有2年了)。
我不想谈什么火候,只是自己感觉用什么方便就用什么!

[ 本帖最后由 guoruimin 于 2008-11-19 08:53 编辑 ]
作者: lipingtababa    时间: 2008-11-19 09:09
"
>>>> 我还见过类似 void fun(Type* & p)的代码,真是难看啊, void fun(Type ** pp)直接明了多了.
>>较之后者,我觉得前者的语义明确多了,不用象指针那样绕来绕去的。
"

-------晕了,你觉得Type* & p比Type ** pp好理解.我还真没想到过.不过多谢你的解答!也多谢各位的解答.

看来用不用引用主要是个风格问题,我在写自己写库的时候基本用指针,但是用STL的时候,就会用引用.

比如我会写 fun(std::map<int,string>& store),不会写成fun(std::map<int,string>* store).因为我觉得对一个不了解其实现的对象取指针有点忐忑.
作者: lipingtababa    时间: 2008-11-19 09:20
原帖由 nicozhou 于 2008-11-19 08:40 发表


这人很固执,FLW说的没错,你觉得指针比引用好用、方便,是因为你没有到时候,到火候。



-----这么说吧,我代码经验确实不多.但是我觉得论坛上,大家都是朋友,谁也不是谁的领导,没必要一副"我很拽,你们听我的没错,不听我的,你自己负责"的态度.别人不会把你当真的.

我还觉得,水平高的人跟水平差的人讨论问题,不耐烦那是正常的.我跟比我更次的菜鸟讲解的时候,也会不耐烦.

但是根本不讨论问题就过来牛逼哄哄的说"散开,散开,你们太菜了,这个问题还讨论,回去多谢代码就明白了".我觉得这人可能是天天被比自己菜的菜鸟追捧,被宠坏了,骄傲得已经不知道自己姓甚名谁了.
作者: cuad    时间: 2008-11-19 10:24
原帖由 whyglinux 于 2008-11-18 23:31 发表
...
>> 我还见过类似 void fun(Type* & p)的代码,真是难看啊, void fun(Type ** pp)直接明了多了.

较之后者,我觉得前者的语义明确多了,不用象指针那样绕来绕去的。

...


朕认为 void fun(Type ** pp) 比  void fun(Type* & p) 更可读。
作者: zhujiang73    时间: 2008-11-19 10:25
标题: 回复 #1 lipingtababa 的帖子
没有引用就不能实现这个:

std::cout << " hello "  << std::endl;

作者: chinaunix3    时间: 2008-11-19 10:30
LZ是聪明的。引用是C++的鸟东西。
作者: lipingtababa    时间: 2008-11-19 10:46
原帖由 zhujiang73 于 2008-11-19 10:25 发表
没有引用就不能实现这个:

std::cout  




可以的,只要你定义操作符返回指针,那么可以这么写

(*(*(std::ccout<<"Hello, ")) << "World") << std::nl;

虽然丑了点.

或者编译器支持的话,可以这么写:

std::cout >> "hello "->>>"World"->>>std::nl.

>>可以定义成其它好看点的符号
作者: flw    时间: 2008-11-19 10:49
原帖由 lipingtababa 于 2008-11-19 10:46 发表

可以的,只要你定义操作符返回指针,那么可以这么写

(*(*(std::ccout>"World"->>>std::nl.

>>可以定义成其它好看点的符号

你在这里说的这个“指针”就是引用。“好看点的符号”就是 <<。
没必要自己骗自己吧。

引用本来就和指针有很多相像的地方,
面临指针存在的问题,
要么扩充指针的功能(Smart pointer),搞出许多和过去不兼容的做法。
要么新发明另一个概念来做这些(引用),让指针和过去完全兼容、
C++ 的发明者选择了后一种做法,你呢?你选择前一种?
作者: flw    时间: 2008-11-19 10:53
楼主要是觉得引用不好,大可以像赵平智一样,把自己的想法付诸于实现,做出一个像样的东西来让大家明白你的想法。
天马行空地想象设计确实很值得赞赏,
可是计算机不完全是理论,还是一个工程,有些看上去很美的东西,如果无法实现,那就只能停留在草稿纸上。

也许你认为 C++ 很丑陋,但它是那个时代的产物,是那个时代的大师权衡利弊的结果。
也许它现在已经不适合了,那你得拿出一个像样点的东西来批判他,这样才有说服力。
作者: nicozhou    时间: 2008-11-19 11:07
原帖由 guoruimin 于 2008-11-19 08:49 发表

不要轻易的说别人不到火候!
或许还有人说认为引用好的不到火候呢!

我刚开始用的是C,后来大多数用C++(6年)。
现在写新东西都用C(有2年了)。
我不想谈什么火候,只是自己感觉用什么方便就用什么!


我也很少用引用,但是我从来不会说引用没指针好,没指针方便。因为C++中既然由这个东西,自然有它存在必要,就像C中一些很少用到的字符一样,你没用它不代表它一点用没有。

LZ的观点,一上来就否认引用的特点,而又拿不出令人信服的理由。

我还说我家的菜刀比你家的砍刀好用呢,我只用来切菜,不会用它砍人。
作者: 太平绅士    时间: 2008-11-19 12:25
原帖由 wzcsoft 于 2008-11-18 21:22 发表

楼主,我来给你你想要的答案,从二者的区别入手。
(1)非空区别。在任何情况下都不能使用指向空值的引用。一个引用必须总是指向某些对象。因此如果你使用一个变量并让他指向一个对象,但是该变量在某些时候也可能不指向任何对象,这是你应该把变量声明为指针,因为这样你可以赋予空值给该变量。相反,如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。不存在指向空值得引用这个事实意味着使用引用的代码效率比使用指针要高。
(2)合法性区别。在使用引用之前不需要测试它的合法性。相反,指针则应该总是被测试,防止其为空。
(3)可修改区别。指针与引用的另一个重要的不同是指针可以被重新赋值以指向另一个不同的对象。但是引用则是总是指向在初始化时被指定的对象,以后不能改变,但是指定的对象其内容可以改变。
(4)应用区别。总的来说,在以下情况下你应该使用指针:一是你考虑到存在不指向任何对象对象的可能(在这种情况下,你能够设置指针为空),二是你需要能够在不同的时刻指向不同的对象(在这种情况下,你能改变指针的指向)。如果总是指向一个对象并且一旦指向一个对象后就不会改变指向,那么你应该使用引用。


这么高的楼,精华就在此贴了!

引用也不是不可修改的,但是比较麻烦,比如引用作为struct的元素包起来,用memcpy赋值struct的方法修改,这样做会不会编译器眼花也是个问题。
总的来说,不赞成强行修改引用。
作者: 太平绅士    时间: 2008-11-19 12:26
原帖由 flw 于 2008-11-19 10:53 发表
楼主要是觉得引用不好,大可以像赵平智一样,把自己的想法付诸于实现,做出一个像样的东西来让大家明白你的想法。
天马行空地想象设计确实很值得赞赏,
可是计算机不完全是理论,还是一个工程,有些看上去很美 ...


赵平智,OIOIC ?
作者: ly321    时间: 2008-11-19 13:52
记得上课时,老师说过一句话
引用更多的是一种暗示

感觉很对
作者: speeder    时间: 2008-11-19 13:54
非特殊要求为啥要强行修改引用,感觉有点违背初衷。想修改数据直接用指针岂不是很方便。
作者: lipingtababa    时间: 2008-11-19 14:56
我不是在挑战Bjarne Stroustrup. 我一个小小的应用程序员,根本就没有改造C++的心.何必一定要我拿出一个像样点的东西来呢

我只是想跟一帮和我差不多,或者差那么一点好,或者那么一点的应用程序员交流下,大家讨论讨论引用的用法,我的标题就很清楚了"你们的代码会用引用吗?",我说的可不是"你们的代码不要用引用."

至于我个人喜好指针,不喜欢引用,完全是我的自由.你没必要对着我  ,你觉得呢
作者: nicozhou    时间: 2008-11-19 15:01
原帖由 lipingtababa 于 2008-11-19 14:56 发表
我不是在挑战Bjarne Stroustrup. 我一个小小的应用程序员,根本就没有改造C++的心.何必一定要我拿出一个像样点的东西来呢

我只是想跟一帮和我差不多,或者差那么一点好,或者那么一点的应用程序员交流下,大家讨 ...


后来写多了代码,我觉得这个玩意的引入完全是多余的,他所有的功能都可以被指针取代(实际上它也是用指针实现的).

这是你的原话。
作者: flw    时间: 2008-11-19 15:03
呵呵,你终于明白当当当当当的道理了啊。
我从一开始就没指望干涉你的喜好,干涉你的自由。
我从一开始就说过了,你爱用不用,觉得什么好用就用什么。
是你死乞白赖求着我给你讲明白为什么引用比指针好用。
现在我稍微给你阐述了一下,你又说我针对你,唉。
作者: lipingtababa    时间: 2008-11-19 15:04
对,没错,就是我的原话,我是这么觉得的,我也是这么做的,尽量不用引用.

我这么一觉得冒犯你了么
作者: lipingtababa    时间: 2008-11-19 15:05
"死乞白赖求着我给你讲明白为什么引用比指针好用"

你确实是被一些人捧得自己不晓得名字怎么写了,你平时签名都签作"Bjarne Stroustrup"吧,大师!
作者: zhujiang73    时间: 2008-11-19 15:06
原帖由 lipingtababa 于 2008-11-19 10:46 发表




可以的,只要你定义操作符返回指针,那么可以这么写

(*(*(std::ccout>"World"->>>std::nl.

>>可以定义成其它好看点的符号


这个丑的有点过了。
作者: bidongliang    时间: 2008-11-19 15:56
何必呢!
作者: nicozhou    时间: 2008-11-19 16:03
原帖由 lipingtababa 于 2008-11-19 15:04 发表
对,没错,就是我的原话,我是这么觉得的,我也是这么做的,尽量不用引用.

我这么一觉得冒犯你了么



这话怎么听起来象前段时间深圳那个高官的口气?

你要想讨论问题,你就别先自己竖靶子,不行吗?
作者: windoze    时间: 2008-11-19 20:34
引用和指针完全是两个东西
引用在初始化的时候一定要绑定引用对象,其后的使用不需要检查有效性,但是引用不能重新绑定到其他对象
指针可以重新绑定到其他对象,但是指针需要用户自己确保它指向了有效的对象。
如果单纯因为&和*的问题去喜欢或者讨厌一样东西,就不需要做技术讨论了
作者: sbc19861004    时间: 2008-11-19 22:21
个人以为Bjarne Stroustrup当年引入引用概念是为了和类概念合作的。
指针本身是可以作为一个对象的句柄(冒用“句柄”一词,找不到好的词汇,取一个能够拿到对象实体的意思),但由于指针本身的面向内存的特征,会给对象带来不安全性,因为对象的内存实现并不像结构体一样只是一些内存区域的顺序组合,对象的实现更应该是一个原子的,编程不可见的统一体,如果对一个对象进行(void*)强制转换,然后随便++一把,后果是不可预知的,而如果要解决这种情况,编译器就要付出比较大的代价。
引用本身就是面向对象(或是面向类型)的概念,就是已语言中的对象(或类型)作为最小单位,可以规定一些类型的转换,这对于编译器是比较好实现的,而对于程序员来说不过是换个概念而已。

个人以为引用比指针更抽象的高级(这里指语言级别的高级,不要误会是好的意思 )些。对语言编程来说跟安全一些。
作者: nuying117    时间: 2008-11-20 13:12
原帖由 lipingtababa 于 2008-11-18 17:36 发表
请举例,请举例.

我举的例子里,都是指针比引用方便而且至关



你这个问题问的太不是地方了,这是中国,这里只有装B的人,没有给你好好举例的人。

你说的问题,我也不懂。 两种方法都可以用,为啥引用要比二维的指针好呢? 是不是用法上简单一些?理解起来方便一些?
作者: A.com    时间: 2008-11-20 13:34
指针太恶心了,我觉得指针这个玩艺纯粹是恶心人的东西。能不用指针还是别用了
作者: sunnyfun    时间: 2008-11-20 16:11
楼主这么问半天还不如google一把呢:

More Effective C++:指针与引用的区别
2006-09-09 07:00 作者: 出处: CSDN 责任编辑:>方舟






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

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

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

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 v(10); // 建立整形向量(vector),大小为10;
// 向量是一个在标准C库中的一个模板
v[5] = 10; // 这个被赋值的目标对象就是操作符[]返回的值

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

*v[5] = 10;

  但是这样会使得v看上去象是一个向量指针。因此你会选择让操作符返回一个引用。

  当你知道你必须指向一个对象并且不想改变其指向时,或者在重载操作符并为防止不必要的语义误解时,你不应该使用指针。而在除此之外的其他情况下,则应使用指针。

作者: 紫色的撒加    时间: 2008-11-20 16:12
原帖由 nuying117 于 2008-11-20 13:12 发表



你这个问题问的太不是地方了,这是中国,这里只有装B的人,没有给你好好举例的人。

你说的问题,我也不懂。 两种方法都可以用,为啥引用要比二维的指针好呢? 是不是用法上简单一些?理解起来方便一些?


没错,lz在这里较真完全没意义,装B的人不会给你举例的。

其实一些人也就是看了别的怎么说就认为自己真的明白了,你问他们有什么意思呢。
作者: sunnyfun    时间: 2008-11-20 16:18
(转)看看编译器对指针和引用分别做了些什么:

  结果是一样的,但是中间的具体实现过程是有所不同的。   
  参数传递指针时将直接对指针指向的地址进行操作   
  传递指针的引用时,通过间接寻址,来实现对[指针指向的地址]进行操作。   
  看看下面一段程序反汇编后的内容就很清楚了   
   
  #include   <iostream>   
  using   namespace   std;   
   
  void   f1(int   *&a)   
  {   
          int   *b;   
          b=a;   
  }   
   
  void   f2(int   *a)   
  {   
          int   *b;   
          b=a;   
  }   
   
  void   main()   
  {   
          int   m=10;   
          int   *n=&m;   
   
          f1(n);   
          f2(n);   
   
  }   
  //---------------------------------------------------------------------------   
   
   
  *   Referenced   by   a   CALL   at   Address:   
  |:00401187         
  |   
  :00401150   55                                             push   ebp   
  :00401151   8BEC                                         mov   ebp,   esp   
  :00401153   51                                             push   ecx   
  //[ebp+08]即为压栈内容:n的有效地址   
  :00401154   8B4508                                     mov   eax,   dword   ptr   [ebp+08]   
  //取得主函数中m的有效地址--》edx   
  :00401157   8B10                                         mov   edx,   dword   ptr   [eax]   
  //b=a;   
  :00401159   8955FC                                     mov   dword   ptr   [ebp-04],   edx   
  :0040115C   59                                             pop   ecx   
  :0040115D   5D                                             pop   ebp   
  :0040115E   C3                                             ret   
   
   
  *   Referenced   by   a   CALL   at   Address:   
  |:00401190         
  |   
  :00401160   55                                             push   ebp   
  :00401161   8BEC                                         mov   ebp,   esp   
  :00401163   51                                             push   ecx   
  //取得压栈内容:n的有效内容(即m的有效地址)   
  :00401164   8B4508                                     mov   eax,   dword   ptr   [ebp+08]   
  //b=a;   
  :00401167   8945FC                                     mov   dword   ptr   [ebp-04],   eax   
  :0040116A   59                                             pop   ecx   
  :0040116B   5D                                             pop   ebp   
  :0040116C   C3                                             ret   
   
   
  --------------->函数开始<----------------------------   
  :00401170   55                                             push   ebp   
  :00401171   8BEC                                         mov   ebp,   esp   
  :00401173   83C4F8                                     add   esp,   FFFFFFF8   
  int   m=10;   
  :00401176   C745FC0A000000                     mov   [ebp-04],   0000000A   
  int   *n=&m;   
  :0040117D   8D45FC                                     lea   eax,   dword   ptr   [ebp-04]   
  :00401180   8945F8                                     mov   dword   ptr   [ebp-08],   eax   
  f1(n);   
  //由于形参是引用变量,所以将n的有效地址压栈   
  :00401183   8D55F8                                     lea   edx,   dword   ptr   [ebp-08]   
  :00401186   52                                             push   edx   
  :00401187   E8C4FFFFFF                             call   00401150   
  :0040118C   59                                             pop   ecx   
  f2(n);   
  //由于形参是指针变量,所以将n的有效内容压栈(即m的有效地址)   
  :0040118D   FF75F8                                     push   [ebp-08]   
  :00401190   E8CBFFFFFF                             call   00401160   
  :00401195   59                                             pop   ecx   
  :00401196   59                                             pop   ecx   
  :00401197   59                                             pop   ecx   
  :00401198   5D                                             pop   ebp   
  :00401199   C3                                             ret   

作者: sunnyfun    时间: 2008-11-20 16:21
无论你传值还是传指针,函数都会生成一个临时变量,   
  但传递一个指针的引用时,不会生成临时变量~~~
作者: w_anthony    时间: 2008-11-20 18:33
void   f1(int   &a);
  void   f2(int   *a);
LS怎么不试一下反汇编上面这种写法?
作者: tyz    时间: 2008-11-20 18:38
没有研究
作者: lauxp    时间: 2008-11-20 21:36
reference is designed for operator like <<
作者: cMEr    时间: 2008-11-20 22:21
看情况定,大的原则似乎书上有。

在战斗中成长

来学习的
作者: openq    时间: 2008-11-20 23:21
学C之前,觉得C++中的引用很好很强大;在我做了一年多的C开发工作之后,已经觉得引用不过如此,更喜欢指针!
作者: abncat    时间: 2008-11-21 09:36
提示: 作者被禁止或删除 内容自动屏蔽
作者: accelerator    时间: 2008-11-21 13:59
引用, 是你一个信任的朋友, 指针, 可能哪天会指向某个茅坑.
作者: puccoon    时间: 2008-11-21 20:03
原帖由 lipingtababa 于 2008-11-18 17:14 发表
我学习C++的时候,已经学习了C,对C的指针有些基本可用的理解,其程度相当于可以使用指针写代码,但不是很理解函数的参数传递机理.

那时候怎么也不明白为什么C++要引入引用,我坚持认为引用肯定有独特之处,之所以 ...




我认为c++引入引用恰恰是和你说的相反,不是因为指针不够强大,而是因为指针太强大了,以至于经常给程序带来潜在的bug,所以才引入引用的

一个很简单的例子,虽然完成同一个传参的工作指针和引用都能完成,但是由于使用了引用之后并不像指针那样可以随意改变指针本身的值可以更好的减少程序的bug,


当然了,如果你是一个高手保证用指针不会出错,那都差不多了
作者: dayip.cn    时间: 2008-11-21 20:06
提示: 作者被禁止或删除 内容自动屏蔽
作者: wishel    时间: 2008-11-21 22:41
不要用指针,指针是邪恶的
除非万不得已再用,太强大的武器很难用好,用不好很容易自伤
作者: hanliu2008    时间: 2008-11-22 13:33
偶倒觉得,爱编程就要爱c,爱c就要爱指针,爱指针就要爱指针的指针
作者: coneagoe    时间: 2008-11-22 21:03
原帖由 lipingtababa 于 2008-11-18 17:14 发表
我学习C++的时候,已经学习了C,对C的指针有些基本可用的理解,其程度相当于可以使用指针写代码,但不是很理解函数的参数传递机理.

那时候怎么也不明白为什么C++要引入引用,我坚持认为引用肯定有独特之处,之所以 ...



从你的话,怀疑你的c是否也掌握的牢固。
举个例子如果你的接口原来是这样:
int fun(int iA);
现在你想换成
int fun(int * pA);
难道你叫你的调用者都去改一遍吗?最讨厌就是和这种一天到晚改接口的合作。这只是引用的一个好处。有你这点时间还不如多看看书。
作者: sbc19861004    时间: 2008-11-22 21:53
原帖由 accelerator 于 2008-11-21 13:59 发表
引用, 是你一个信任的朋友, 指针, 可能哪天会指向某个茅坑.

哈哈,顶!喜欢这种说话风格,很有hacker气质。
作者: wishel    时间: 2008-11-23 00:37
原帖由 coneagoe 于 2008-11-22 21:03 发表



从你的话,怀疑你的c是否也掌握的牢固。
举个例子如果你的接口原来是这样:
int fun(int iA);
现在你想换成
int fun(int * pA);
难道你叫你的调用者都去改一遍吗?最讨厌就是和这种一天到晚改接口的合 ...


说得好。
只看到指针的强大方便的一面,没看到其危险和邪恶的另一面的人,对C和指针的认识都是肤浅的
所以没有必要在这里跟别人争什么,想进步的话承认自己的不足。多向别人学习
肤浅无知没什么,但是拿出来卖弄就不对了
作者: chinesedragon    时间: 2008-11-23 09:00
学习了~~~~~~~
作者: xyz300    时间: 2008-11-23 15:44
提示: 作者被禁止或删除 内容自动屏蔽
作者: yhb04    时间: 2008-11-23 15:58
原帖由 wishel 于 2008-11-23 00:37 发表


说得好。
只看到指针的强大方便的一面,没看到其危险和邪恶的另一面的人,对C和指针的认识都是肤浅的
所以没有必要在这里跟别人争什么,想进步的话承认自己的不足。多向别人学习
肤浅无知没什么,但是拿 ...

开玩笑。
指针和引用谁更好本身就是个人喜好问题,你喜欢引用,你觉得它好,它很安全,那你就用呗。用得着上升到个人水平的高度去解释吗?
照你的说法,我还觉得只看到指针危险,引用方便安全的人对指针和C的认识很肤浅呢。
有些地方(尤其是底层OS)就需要使用指针的灵活强大。我看你才肤浅无知。
作者: wishel    时间: 2008-11-23 22:46
哈哈,争论谁更肤浅就没意义了
你如果是C程序员,我没话说,我是个C++程序员,不喜欢C的很多东西
不过如果一个自称C++程序员大叫引用没用指针最好,偶是要鄙视一下的
作者: system888net    时间: 2008-11-23 23:57
大家在从不同的角度对这个问题进行补充呢!
1.对于"引用" 有他存在的道理,但也并没有因为"引用"的出现而废除指针.
2.对于一个功能f的实现可以用"引用",也可以不用,这取决与个人或团队的喜好和思维方式.
3.对于使用这个功能f的用户而言,他只关心结果:稳定性和易用性等, 那么可以评估一下用"指针"或用"引用"对这个结果的影响是否大过其他因素?
  "指针"也好"引用"也好都是给程序员提供的一个方法而已,其目的不外呼让程序员按自己的所长用合适的功能完成软件的目标功能而已.
作者: lipingtababa    时间: 2008-11-24 01:23
原帖由 wishel 于 2008-11-23 22:46 发表
哈哈,争论谁更肤浅就没意义了
你如果是C程序员,我没话说,我是个C++程序员,不喜欢C的很多东西
不过如果一个自称C++程序员大叫引用没用指针最好,偶是要鄙视一下的



---你真好玩,你的回帖什么信息都没提供,就引进了“肤浅”两个字,还怕我们不懂这个词的释义,现身说法展示了一下。

[ 本帖最后由 lipingtababa 于 2008-11-24 01:27 编辑 ]
作者: cjaizss    时间: 2008-11-24 01:33
好不好是每个人自己的感觉.C++为每个人提供了各种编程的手段,它只是提供了,用不用是使用者的问题.觉得多余就不用,觉得好就用.
btw:鄙人从不用C++写程序,所以到目前为止,C++提供的手段再多也与我没关系
作者: cjaizss    时间: 2008-11-24 02:03
另外,你可以去接受,可以拒绝,不要去想是否多余,因为它既然支持了,就有它的道理.你不用,自然有别人用的欢呢.
否则,我还觉得C语言下struct,union,enum三个都是多余的呢,因为没有它们三个,程序照写,烦琐一点而已,但是描述照样没有功能性的影响.
作者: samon_fu    时间: 2008-11-24 02:39
标题: 回复 #1 lipingtababa 的帖子
引用的可读性好得多了。

等你吃指针的亏了,你就明白了,现在说也没太多用处的。有些东西是工程中才能得来的。
作者: hfgv    时间: 2008-11-24 09:48
原帖由 cjaizss 于 2008-11-24 02:03 发表
另外,你可以去接受,可以拒绝,不要去想是否多余,因为它既然支持了,就有它的道理.你不用,自然有别人用的欢呢.
否则,我还觉得C语言下struct,union,enum三个都是多余的呢,因为没有它们三个,程序照写,烦琐一点而已,但是描述照样没有功能性的影响.


厮!
你竟敢说C语言的struct,union,enum三个都是多余的!
厮!
作者: hfgv    时间: 2008-11-24 10:22
C++的引用是鸡肋不如的东西!不要理它。
作者: hfgv    时间: 2008-11-24 10:25
C++里有很多垃圾东西都违背了社会分工协作的理念,引用就是其一。
作者: yhb04    时间: 2008-11-24 11:20
原帖由 wishel 于 2008-11-23 22:46 发表
哈哈,争论谁更肤浅就没意义了
你如果是C程序员,我没话说,我是个C++程序员,不喜欢C的很多东西
不过如果一个自称C++程序员大叫引用没用指针最好,偶是要鄙视一下的

学过C++,看过几本C++的书就很了不起吗?l连C都没好好用过就大加评论C和C++的特性怎么怎么滴。
我学过C++,也用过它写过不少程序,客观的说,C++的一些新特性是不错,像类,虚函数,泛型编程。。但是它也有很多
鸡肋特性,而且搞得复杂无比。
我也看过一些C++方面的经典书,像Thinking in C++等等,发现介绍C++的书有一个通病:它在介绍C++的某个特性时,
总喜欢夸大C中对应特性的不足,鼓吹C++新特性的优势。没错,C中确实有不少缺陷,但是绝对没有他们所说的那么严重,
有些肤浅的人估计会把这些书当圣经一样的看待,毫无批判的接受书中所有观点。
作者: hfgv    时间: 2008-11-24 12:28
标题: 回复 #99 yhb04 的帖子
不要说C语言有缺陷,以免误导初学者。除了面向对象外,C语言在其他方面已几近完美。不像垃圾C++,C语言没有先天的不足。好歹没让那些设计C++的愚蠢家伙们参与C语言的设计,免得玷污了我们伟大的C。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2