C++中引用与指针的区别(详细介绍)

发表于:2015-3-13 09:49

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:shiddong    来源:51Testing软件测试网采编

  2)以下是“指针传递”的示例程序。由于Func2 函数体内的x 是指向外部变量n 的指针,改变该指针的内容将导致n 的值改变,所以n 的值成为10.
  void Func2(int *x)
  {
  (* x) = (* x) + 10;
  }
  ⋯
  int n = 0;
  Func2(&n);
  cout << “n = ” << n << endl; // n = 10
  3)以下是“引用传递”的示例程序。由于Func3 函数体内的x 是外部变量n 的引用,x和n 是同一个东西,改变x 等于改变n,所以n 的值成为10.
  void Func3(int &x)
  {
  x = x + 10;
  }
  &#8943;
  int n = 0;
  Func3(n);
  cout << “n = ” << n << endl; // n = 10
  对比上述三个示例程序,会发现“引用传递”的性质象“指针传递”,而书写方式象“值传递”。实际上“引用”可以做的任何事情“指针”也都能够做,为什么还要“引用”这东西?
  答案是“用适当的工具做恰如其分的工作”。
  指针能够毫无约束地操作内存中的如何东西,尽管指针功能强大,但是非常危险。
  就象一把刀,它可以用来砍树、裁纸、修指甲、理发等等,谁敢这样用?
  如果的确只需要借用一下某个对象的“别名”,那么就用“引用”,而不要用“指针”,以免发生意外。比如说,某人需要一份证明,本来在文件上盖上公章的印子就行了,如果把取公章的钥匙交给他,那么他就获得了不该有的权利。
  ——————————
  摘自「高质量c++编程」
  指针与引用,在More Effective C++ 的条款一有详细讲述,我给你转过来
  条款一:指针与引用的区别
  指针与引用看上去完全不同(指针用操作符‘*’和‘->’,引用使用操作符‘。’),但是它们似乎有相同的功能。指针与引用都是让你间接引用其他对象。你如何决定在什么时候使用指针,在什么时候使用引用呢?
  首先,要认识到在任何情况下都不能用指向空值的引用。一个引用必须总是指向某些对象。因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量。相反,如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。
  “但是,请等一下”,你怀疑地问,“这样的代码会产生什么样的后果?”
  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)
  当你知道你必须指向一个对象并且不想改变其指向时,或者在重载操作符并为防止不必要的语义误解时,你不应该使用指针。而在除此之外的其他情况下,则应使用指针假设你有
  void func(int* p, int&r);
  int a = 1;
  int b = 1;
  func(&a,b);
  指针本身的值(地址值)是以pass by value进行的,你能改变地址值,但这并不会改变指针所指向的变量的值,
  p = someotherpointer; //a is still 1
  但能用指针来改变指针所指向的变量的值,
  *p = 123131; // a now is 123131
  但引用本身是以pass by reference进行的,改变其值即改变引用所对应的变量的值
  r = 1231; // b now is 1231
  尽可能使用引用,不得已时使用指针。
  当你不需要“重新指向”时,引用一般优先于指针被选用。这通常意味着引用用于类的公有接口时更有用。引用出现的典型场合是对象的表面,而指针用于对象内部。
  上述的例外情况是函数的参数或返回值需要一个“临界”的引用时。这时通常最好返回/获取一个指针,并使用 NULL 指针来完成这个特殊的使命。(引用应该总是对象的别名,而不是被解除引用的 NULL 指针)。
  注意:由于在调用者的代码处,无法提供清晰的的引用语义,所以传统的 C 程序员有时并不喜欢引用。然而,当有了一些 C++ 经验后,你会很快认识到这是信息隐藏的一种形式,它是有益的而不是有害的。就如同,程序员应该针对要解决的问题写代码,而不是机器本身。
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号