简体   繁体   中英

Is there a difference, or preferred between ptr** and ptr*& in C++ when calling functions?

Is there a difference or preferred way of altering a pointer in a function? Take this snippet for example

    void change(int** ptr) {
        **ptr = 50;
        *ptr = nullptr;
    }

    void change(int*& ptr) {
        *ptr = 50;
        ptr = nullptr;
    }

    int main()
    {
        int a = 5;

        int* ptr = &a;
        int** ptr2 = &ptr;

        std::cout << "value: " << a << std::endl;
        std::cout << "value: " << ptr << std::endl;
        std::cout << "value: " << ptr2 << std::endl;

        change(ptr2);
        //change(ptr);

        std::cout << "value: " << a << std::endl;
        std::cout << "value: " << ptr << std::endl;
        std::cout << "value: " << ptr2 << std::endl;


        system("pause");

    }

It seems like both of the change functions can achieve what I'm asking, but I'm not sure on the difference, other than the reference function doesn't create a copy of the pointer?

You can have a null pointer, but not a null reference.

You can supply the first with nullptr , and it will compile 1 , because there is an implicit conversion from std::nullptr_t to int** . If you tried to supply the second with nullptr , it will fail. The best match would be the conversion std::nullptr_t to int* , but you can't bind a mutable reference to a temporary.

I go over various situations for different ways of parameter passing in this answer , which also includes object ownership considerations (with std::unique_ptr )

1. The behaviour will be undefined, because you dereference it.

Is there a difference ... between ptr** and ptr*& ...

Yes. The former is a pointer, to an object of type ptr* , while the latter is a reference to an object of type ptr* .

or preferred ...

 void change(int** ptr) { **ptr = 50; *ptr = nullptr; } void change(int*& ptr) { *ptr = 50; ptr = nullptr; } 

Advantages of a reference

You'll find that the reference is implicitly indirected, which makes the syntax simpler and that usually helps readability. This is particularly important in case of reference / pointer to a pointer. Same advantage applies to getting a reference: You don't need to use the address-of operator.

Another advantage is that a reference cannot be reassigned to refer to another object. This makes it simpler to read programs that use references, since you don't need to figure out whether a reference is reassigned within a long algorithm; You know that it isn't.

Another advantage is that a reference cannot be null. Therefore you don't need to check for such eventuality within the function. If you pass null to the first example function, the behaviour would be undefined, which is a very bad thing.

Disadvantages of a reference

You'll find that the reference is implicitly indirected. This can be confusing to people who are familiar with only value types (C programmers).

Another disadvantage is that a reference cannot be reassigned to refer to another object. This appears to not be a problem for your function since you don't need to refer to more than one object, but in general, there are situations where it would be useful.

Another disadvantage is that a reference cannot be null. This appears to not be a problem for your function which is presumably never intended to handle such case. But in general, there are situations where you want to represent a referential relation to non-existing object.


Preferences are personal, but in my opinion, the advantages of the reference outweigh the disadvantages, except when you need one of the features that are not possible (nullability, re-assignment)

It's largely a matter of personal taste.

That said, when calling void change(int** ptr) , because you'd tend to pass the address of something using & , it is clearer at the calling site that the "something" could be modified by the function. If you use the int*& ptr overload, it's not as clear as the calling syntax is identical for pass-by-value and pass-by-reference.

Aside from the above, I tend to use pointers as function parameters if nullptr is allowed, and references if not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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