【问题标题】:Reference vs. pointer参考与指针
【发布时间】:2014-02-19 15:21:20
【问题描述】:

有什么区别?因为这个:

int Value = 50;
int *pValue = &Value;

*pValue = 88;

和参考版本做同样的事情:

int Value = 50;
int &rValue = Value;

rValue = 88;

哪个更好用?谢谢。

【问题讨论】:

  • 值得注意的是,引用经常被用作函数的参数。 (如果在同一范围内,上面的 sn-p 几乎没有意义——如果实际变量很容易获得,为什么还要声明别名?)更改该值的函数的引用参数可能会令人困惑,因为调用者无法判断是否在不查看函数签名的情况下,它是否是参考。在这种情况下讨论指针与引用可能更重要。

标签: c++ pointers reference


【解决方案1】:

在这种情况下,它们是等价的。

你使用哪个并不重要,也不是“最好的”。

如果您真的想在它们之间进行选择,那么引用可能更惯用。我通常尽可能地坚持引用,因为我的强迫症喜欢它:它们感觉“更紧密”,不能重新绑定(无论你是否注意到),并且不需要取消引用来获得价值。

但我不知道对于此类案件的问题有任何普遍共识。

另外请注意,如果您的实现不使用指针实现引用,则两者可能无法编译为相同的代码,尽管我知道没有这样的实现,而且您无论如何也不会注意到差异。

【讨论】:

  • @Quest:还有其他情况,但也有使用指针有效而使用引用无效的情况,例如,如果您尝试将句柄重新绑定到不同的 int ,或者如果您想持有“空”句柄等。当人们询问指针与引用时,我尽量不进行概括。
  • @LightnessRacesinOrbit 另外,我相信 reference 与类型相关联。 我们可以有一个 void* 类型的指针,它是通用的,但我不知道有任何情况参考是通用的
  • @SimpleGuy:确实; C++ prohibits that。没有可以通过引用公开的“接口”,并且由于这是透明地发生的(即没有取消引用),因此允许它会有点奇怪。尽管如此,理论上它可以像 void* 一样被允许 - 你必须在“使用”它之前将它转换为其他东西。
【解决方案2】:

指针是内存位置的地址。您可以更改该地址的值以指向不同的内存地址。

引用是变量的别名。您只能在声明期间分配此别名。声明后,您无法更改引用是哪个变量的别名。


引用不能进行以下指针分配。

int a = 10;
int b = 20;

int* pInt = NULL; // A pointer pointing at nothing.
pInt = &a; // pInt now points at a
pInt = &b; // pInt now points at b

至于哪个更好,这完全取决于上下文。

我使用方法和函数参数的引用。

void updateFoo(Foo& foo)

我使用对复杂对象的引用。

Foo& foo = bar.getBaz().getFoo(); // easy access to foo

我对动态分配的对象使用指针。

Foo* pFoo = new Foo();

我对可能指向不同值(包括根本没有值)的事物使用指针。

Foo* pFoo = NULL;

if (condition1)
    pFoo = &foo1;
else (condition2)
    pFoo = &foo2;

作为一般规则,我默认使用引用并在引用限制导致问题的地方使用指针。

【讨论】:

  • 由于问题是关于指针与引用,那么我假设这仅意味着函数参数,并且指针参数是指针的副本,因此函数无法更改实际指针。该参数必须是指向指针的指针才能更改原始指针。引用的一个问题是,在查看调用代码时,无法知道参数是通过值传递还是通过引用传递。这只能通过查看可能位于另一个源文件中的函数原型或函数本身来完成。
  • 另外,这里有点切线,但在我看来,您提议使用对别名复杂对象的引用有点滥用,因为您基本上违反了得墨忒耳法则,这表明OO设计中的问题。话虽如此,我不是 C(++) 程序员,出于某种原因,这种做法可能比其他语言(更多)可以接受。
【解决方案3】:

区别在于:

引用是对象的别名,与对象的地址相同。

int a;         //  address of   a : 0x0012AB
int &ref = a;  //  address of ref : 0x0012AB (the same)

引用必须初始化

int &ref = a; // GOOD, is compiling
int &ref;     // BAd, is not compiling

指针是另一个保存地址的变量:

int a = 5;     //  address of a : 0x0012AB 
int *p = &a;   //  address of p : 0x0012AF (is different )

// value of a is 5
// value of p is 0x0012AB  (address of a)

指针可以为NULL

int *p = NULL;

【讨论】:

    【解决方案4】:

    我的经验法则是倾向于使用引用或 const 引用,除非需要指针。

    引用可能不会被重新定位,并且在语法上更清晰。该引用还向您保证该引用不是NULL

    为了方便使用数组时,我也可以使用指针。

    【讨论】:

    • 引用本身并没有“保证”,真的。在定义明确的程序中不会有“空引用”,但这更多取决于程序员而不是引用功能。
    • 是否有一个(非黑客)示例,其中引用指向无效变量?听起来很有趣,如何实现这样的目标
    • @LightnessRacesinOrbit 这就是我写“给你”的原因。如果你被传递了一个空引用,那么 UB 已经发生了。
    • @MatthiasBonora 也许您正在寻找引用超出范围或在引用之前被破坏的情况。如果容器(例如向量)在调整大小期间重新分配其存储空间,就会发生这种情况。
    【解决方案5】:

    我同意贾斯汀的回答,并想用最小的例子来澄清它。

    假设你不太记得二维图像几何库的语法:是吗

    bool BooleanOr( const Bitmap & input1, const Bitmap & input2, Bitmap * output );
    

    是吗

    bool BooleanOr( Bitmap * output, const Bitmap & input1, const Bitmap & input2 );
    

    如果在您的公司中,每个人都使用指针作为输出并使用 const 引用作为输入,那么几乎不可能犯错误:当您看到诸如

    之类的调用时

    BooleanOr(thisBitmap, thatBitmap, & anotherBitmap);

    你马上就知道语法了。

    【讨论】:

      【解决方案6】:

      这里有很好的答案。我想指出引用的 2 个具体用法:-

      案例 1:在实现 operator[] 时。此运算符通常需要返回 something 可以用作赋值的目标 示例:-

      vector<int> v(20);
      v[1] = 5; //The target of the assignment is the return value of operator []
      

      这里operator [] 返回vector 中指定索引处元素的引用。如果 operator [] 被设计为返回一个 pointer 到指定索引处的元素,那么第二行必须这样写:-

      *v[1] = 5
      

      现在v 看起来像是一个指针向量 - 绝对不是!!因此,为了保持理智 - operator [] 返回一个 reference 而不是 pointer 指向向量中的索引元素

      案例 2:引用不需要明确的 null 检查。一些答案已经谈到了它 - 想使用代码 sn-p 来展示优势:-

      void fun(const int& val)
      {
        cout << val;
      }
      
      void fun(const int* val)
      {
        if (val){ //Additional overhead with pointers
          cout << *val;
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-08-03
        • 1970-01-01
        • 2015-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多