"reference of pointer"有什么意义吗?

Is there any point of "reference of pointer"?

我不明白指针类型的引用是如何工作的。

  1. 是否有性能差异?

  2. 如果编译的话,汇编级别有区别吗?

  3. 指针类型的引用有没有意义?

vector<Figure*> vFigureList;

//auto&
for(auto& pFigure : vFigureList)
{
    pFigure->draw();
    delete pFigure;
}

//auto
for(auto pFigure : vFigureList)
{
    pFigure->draw();
    delete pFigure;
}

//Figure*
for(Figure* pFigure : vFigureList)
{
    pFigure->draw();
    delete pFigure;
}

//Figure*&
for(Figure*& pFigure : vFigureList)
{
    pFigure->draw();
    delete pFigure;
}
  1. Is there any point to reference of pointer type?

当你想对它们进行修改时。例如

// when modify pointers themselves in vFigureList
for(auto& pFigure : vFigureList)
{
    delete pFigure;
    pFigure = nullptr; // modify pointers (in vFigureList) to nullptr
}

基本上就是intint&的区别。

引用往往作为指针实现,因此您的 Figure*& 本质上是一个指向指针的指针。

Is there any performance difference?

Is there any assembly level difference if they compiled?

引用需要在使用前取消引用,但是具体细节取决于实现。在您的示例中,您的编译器更有可能完全优化它并直接 access/modify 向量中的值。在这种情况下,pFigure(即使作为一个值)可​​能真的是一个别名,根本不映射到任何物理变量。

Is there any point to reference of pointer type?

除非你想直接修改指针本身,正如其他答案已经指出的那样。

编译后,引用就像指针一样,它们提供了一定程度的间接性。但是它们在 C++ 中有不同的用途:

  • 它们必须在定义时初始化,因此更安全,就像一个 const 指针。
  • 无需使用 & 运算符的地址来声明它们指向的位置。
  • 无需使用 *

Is there any performance difference?

是的,引用会引起一定程度的指针取消引用,就像普通指针一样。

Is there any assembly level difference if they compiled?

与普通变量相比,是的,额外的间接级别。与指针相比,不,编译后引用和指针是相同的。

Is there any point to reference of pointer type?

是的,如果您需要指向指针的指针,但又想要引用的安全性和便利性。

这是编译器资源管理器上的一个示例(如果 link 过期,请使用下面的相同来源): https://godbolt.org/z/h3WzdPWa1

在没有优化的情况下编译时(不推荐,仅用于此 Compiler Explorer 示例的说明):

  • 直接访问使用三个汇编指令
  • 一级间接(指针和引用)使用五个指令
  • 两级间接寻址(引用指针和指针指向指针)使用七条指令

这有助于说明引用实际上是引擎盖下的指针,具有相同的性能影响。

int num();
int* num_ptr();

int main() {
    int i = num();
    
    int& r = i;
    int* p = num_ptr();

    int*& pr = p;
    int** pp = &p;

    // Direct access
    i += 3;

    // One level of indirection
    r += 5;   
    *p += 7;

    // Two levels of indirection
    *pr += 11;
    **pp += 13;

    return 0;
}