指针变量和引用变量之间的区别是什么?


当前回答

如果遵循传递给函数的参数的约定,则可以使用引用和指针之间的差异。Const引用用于传递到函数中的数据,指针用于传递出函数的数据。在其他语言中,您可以使用诸如In和out之类的关键字来明确表示这一点。在C++中,您可以(按照约定)声明等价的。例如

void DoSomething(const Foo& thisIsAnInput, Foo* thisIsAnOutput)
{
   if (thisIsAnOuput)
      *thisIsAnOutput = thisIsAnInput;
}

使用引用作为输入和指针作为输出是Google风格指南的一部分。

其他回答

什么是C++参考(针对C程序员)

引用可以被视为具有自动间接寻址的常量指针(不要与指向常量值的指针混淆!),即编译器将为您应用*运算符。

所有引用都必须使用非空值初始化,否则编译将失败。既不可能获得引用的地址——地址运算符将返回被引用值的地址——也不可能对引用进行算术运算。

C程序员可能不喜欢C++引用,因为当发生间接寻址时,或者当参数通过值或指针传递而不查看函数签名时,C++引用将不再明显。

C++程序员可能不喜欢使用指针,因为它们被认为是不安全的——尽管引用实际上并不比常量指针更安全,但在大多数情况下除外——缺乏自动间接寻址的便利性,并且具有不同的语义内涵。

考虑C++常见问题解答中的以下语句:

即使引用通常使用底层汇编语言,请不要将引用视为指向对象的有趣指针。引用是对象。它是不是指向对象的指针,也不是对象的副本。它是对象

但如果引用真的是对象,那么怎么会有悬空引用呢?在非托管语言中,引用不可能比指针更“安全”——通常没有办法跨范围可靠地别名值!

为什么我认为C++引用有用

来自C背景的C++引用可能看起来有点傻,但在可能的情况下,仍应使用它们而不是指针:自动间接寻址很方便,在处理RAII时引用变得特别有用,但这并不是因为任何已知的安全优势,而是因为它们使编写惯用代码不那么困难。

RAII是C++的核心概念之一,但它与复制语义进行了非平凡的交互。通过引用传递对象可以避免这些问题,因为不需要复制。如果语言中没有引用,则必须使用指针,这样使用起来更麻烦,从而违反了语言设计原则,即最佳实践解决方案应该比替代方案更容易。

除了这里的所有答案,

可以使用引用实现运算符重载:

my_point operator+(const my_point& a, const my_point& b)
{
  return { a.x + b.x, a.y + b.y };
}

使用参数作为值将创建原始参数的临时副本,而使用指针将不会调用此函数,因为指针算法。

简单地说,我们可以说引用是变量的替代名称,指针是保存另一个变量地址的变量。例如

int a = 20;
int &r = a;
r = 40;  /* now the value of a is changed to 40 */

int b =20;
int *ptr;
ptr = &b;  /*assigns address of b to ptr not the value */

如果遵循传递给函数的参数的约定,则可以使用引用和指针之间的差异。Const引用用于传递到函数中的数据,指针用于传递出函数的数据。在其他语言中,您可以使用诸如In和out之类的关键字来明确表示这一点。在C++中,您可以(按照约定)声明等价的。例如

void DoSomething(const Foo& thisIsAnInput, Foo* thisIsAnOutput)
{
   if (thisIsAnOuput)
      *thisIsAnOutput = thisIsAnInput;
}

使用引用作为输入和指针作为输出是Google风格指南的一部分。

可以重新分配指针:int x=5;整数y=6;int*p;p=&x;p=&y;*p=10;断言(x==5);断言(y==10);引用不能重新绑定,必须在初始化时绑定:int x=5;整数y=6;整数&q;//错误int&r=x;指针变量有它自己的标识:一个独特的、可见的内存地址,可以用一元&运算符获取,还有一定的空间,可以用sizeof运算符测量。对引用使用这些运算符将返回与引用绑定到的任何对象相对应的值;引用自身的地址和大小是不可见的。由于引用以这种方式假定原始变量的身份,因此可以方便地将引用视为同一变量的另一个名称。int x=0;int&r=x;int*p=&x;int*p2=&r;断言(p==p2);//&x==&r断言(&p!=&p2);可以将任意嵌套的指针指向提供额外间接级别的指针。引用仅提供一个间接级别。int x=0;整数y=0;int*p=&x;int*q=&y;int**pp=&p;**pp=2;pp=&q;//*pp现在是q**pp=4;断言(y==4);断言(x==2);指针可以指定为nullptr,而引用必须绑定到现有对象。如果您足够努力,您可以将引用绑定到nullptr,但这是未定义的,并且行为不一致。/*以下代码未定义;你的编译器可以优化它*不同的是,发出警告,或者干脆拒绝编译*/int&r=*static_cast<int*>(nullptr);//在GCC 10下打印“空”标准::cout<<(&r!=空指针? “not null”:“null”)<<std::endl;bool f(int&r){return&r!=nullptr;}//根据GCC 10打印“非空”标准::cout<<(f(*static_cast<int*>(nullptr))? “not null”:“null”)<<std::endl;但是,可以引用值为nullptr的指针。指针可以遍历数组;您可以使用++转到指针指向的下一个项目,使用+4转到第五个元素。这与指针指向的对象的大小无关。指针需要用*解引用以访问它指向的内存位置,而引用可以直接使用。指向类/结构的指针使用->访问其成员,而引用使用。。引用不能放入数组,而指针可以(由用户@litb提及)Const引用可以绑定到临时项。指针不能(不是没有间接指向):常量int&x=int(12);//法定C++int*y=&int(12);//取临时地址是非法的。这使得const&更便于在参数列表等中使用。