繁体   English   中英

在 C++ 中通过引用传递指针的原因?

[英]Reason to Pass a Pointer by Reference in C++?

在什么情况下你想在 c++ 中使用这种性质的代码?

void foo(type *&in) {...}

void fii() {
  type *choochoo;
  ...
  foo(choochoo);
}

如果您需要修改指针而不是指针指向的对象,您可能希望通过引用传递指针。

这类似于为什么使用双指针; 使用对指针的引用比使用指针稍微安全一些。

50% 的 C++ 程序员喜欢在删除后将指针设置为 null:

template<typename T>    
void moronic_delete(T*& p)
{
    delete p;
    p = nullptr;
}

如果没有引用,您只会更改指针的本地副本,而不会影响调用者。

大卫的回答是正确的,但如果还是有点抽象,这里有两个例子:

  1. 您可能希望将所有释放的指针归零以更早地捕获内存问题。 你会做的 C 风格:

     void freeAndZero(void** ptr) { free(*ptr); *ptr = 0; } void* ptr = malloc(...); ... freeAndZero(&ptr);

    在 C++ 中做同样的事情,你可能会这样做:

     template<class T> void freeAndZero(T* &ptr) { delete ptr; ptr = 0; } int* ptr = new int; ... freeAndZero(ptr);
  2. 在处理链表时 - 通常简单地表示为指向下一个节点的指针:

     struct Node { value_t value; Node* next; };

    在这种情况下,当您插入空列表时,您必须更改传入指针,因为结果不再是NULL指针。 在这种情况下,您从函数修改外部指针,因此它的签名中将包含对指针的引用:

     void insert(Node* &list) { ... if(!list) list = new Node(...); ... }

这个问题中有一个例子。

我不得不使用这样的代码来提供函数来为传入的指针分配内存并返回其大小,因为我的公司使用 STL 向我“对象”

 int iSizeOfArray(int* &piArray) {
    piArray = new int[iNumberOfElements];
    ...
    return iNumberOfElements;
 }

这不好,但指针必须通过引用传递(或使用双指针)。 如果不是,则将内存分配给指针的本地副本(如果按值传递会导致内存泄漏)。

一个例子是当你编写一个解析器函数并向它传递一个源指针来读取时,如果该函数应该将该指针向前推到最后一个被解析器正确识别的字符后面。 使用对指针的引用可以清楚地表明该函数将移动原始指针以更新其位置。

通常,如果要将指针传递给函数并让它将原始指针移动到其他位置,而不是仅移动它的副本而不影响原始指针,则可以使用对指针的引用。

另一种可能需要这样做的情况是,如果您有 stl 指针集合并想使用 stl 算法更改它们。 c++98 中 for_each 的示例。

struct Storage {
  typedef std::list<Object*> ObjectList;
  ObjectList objects;

  void change() {
    typedef void (*ChangeFunctionType)(Object*&);
    std::for_each<ObjectList::iterator, ChangeFunctionType>
                 (objects.begin(), objects.end(), &Storage::changeObject);
  }

  static void changeObject(Object*& item) {
    delete item;
    item = 0;
    if (someCondition) item = new Object();
  } 

};

signature you have copy of pointer, not original one.否则,如果您使用签名,您将拥有指针的副本,而不是原始指针。

参考下面的代码:当我们将 x 作为Node *x传递时,将创建一个新变量,其地址与调用者 function 传递的地址相同。

  1. 如果修改指针指向的值,该更改将反映在调用者 function 变量中。
  2. 但是如果我们改变指针本身的值,它不会反映在调用者 function 中,因为被调用者 function 拥有传递指针的副本而不是原始指针本身。
    void increment(int *x) {
        (*x)++;
        x++;
        cout << x << endl;  // prints 0x7ffe9f8e1900
    }
    
    int main() {
        int a = 10;
        int *x = &a;
        increment(x);
        cout << *x << endl; // prints 11
        cout << x << endl;  // prints 0x7ffe9f8e18fc
        return 0;
    }

现在,检查下面的代码:当我们将 x 作为Node *&x传递时,我们传递了调用者 function 中存在的原始变量的引用,这意味着这两个变量(调用者和被调用者根)相同,它们的名称可能不同。

  1. 如果我们通过指针修改值指针,该更改将反映在调用者 function 变量中。
  2. 现在,如果我们更改指针本身的值,它也会反映在调用者 function 变量中。
    void increment(int* &x)
    {
        (*x) ++;
        cout << *x << endl; // prints 11
        x++;
        cout << x << endl;  // prints 0x7ffe9f8e1900
    }

    int main()
    {
        int a = 10;
        int *x = &a;
        increment(x);
        cout << *x << endl; // prints garbage
        cout << x << endl;  // prints 0x7ffcbeac5ea0
        return 0;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM