指针与引用的区别

本文深入探讨了C++中的指针和引用的概念,详细解释了它们在内存分配、操作方式、空值表现及使用场景上的区别。通过实例解析,帮助读者理解何时选择使用指针或引用,以提升编程效率和代码质量。

出处:你的博客网(yourblog.org)

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

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

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

  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库中的一个模板(见条款35) 
   v[5] = 10; // 这个被赋值的目标对象就是操作符[]返回的值 

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

  *v[5] = 10; 

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

   当你知道你必须指向一个对象并且不想改变其指向时,或者在重载操作符并为防止不必要的语义误解时,你不应该使用指针。而在除此之外的其他情况下,则应使用指针 。
### 指针引用区别 在C++编程语言中,指针引用是两种用于间接访问变量的方式,但它们在语法、实现以及使用场景上存在显著差异。以下是详细的对比分析: #### 1. 声明初始化 - 指针通过`*`符号声明,可以不立即初始化[^2]。例如: ```cpp int *p; // 声明一个指针,未初始化 ``` - 引用通过`&`符号声明,必须在声明时初始化,并且一旦绑定到某个对象后,不能重新绑定到其他对象[^3]。例如: ```cpp int a = 10; int &ref = a; // 引用必须初始化并绑定到变量a ``` #### 2. 可空性 - 指针可以为`nullptr`,表示它不指向任何有效的内存地址[^2]。例如: ```cpp int *p = nullptr; // 指针为空 ``` - 引用不能为空,它总是绑定到某个有效的对象[^3]。 #### 3. 解引用 - 指针需要显式解引用操作符`*`来访问其所指向的对象的值[^2]。例如: ```cpp int a = 10; int *p = &a; cout << *p; // 输出a的值 ``` - 引用自动解引用,直接使用引用名即可访问所绑定对象的值[^3]。例如: ```cpp int a = 10; int &ref = a; cout << ref; // 输出a的值 ``` #### 4. 地址操作 - 指针本身有地址,可以通过`&`获取其地址。例如: ```cpp int a = 10; int *p = &a; cout << &p; // 输出指针p的地址 ``` - 引用没有独立的地址,它是其所绑定对象的别名,无法获取引用本身的地址。 #### 5. 多级间接支持 - 指针支持多级间接(即多级指针),例如`int**`表示指向指针指针[^2]。 - 引用不支持多级间接,只能直接绑定到某个对象[^3]。 #### 6. 使用场景 - 指针通常用于动态内存分配、数据结构(如链表、树等)以及函数返回值等场景[^1]。例如: ```cpp int *p = new int(10); // 动态分配整数 ``` - 引用常用于避免拷贝大型对象、作为函数参数传递以提高效率,同时保证不会修改原对象(如常量引用)[^3]。例如: ```cpp void print(const std::string& str) { cout << str; // 避免拷贝字符串 } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值