When to use references vs. pointers

前端 未结 17 2102
一向
一向 2020-11-22 02:27

I understand the syntax and general semantics of pointers versus references, but how should I decide when it is more-or-less appropriate to use references or pointers in an

相关标签:
17条回答
  • 2020-11-22 03:20

    Just putting my dime in. I just performed a test. A sneeky one at that. I just let g++ create the assembly files of the same mini-program using pointers compared to using references. When looking at the output they are exactly the same. Other than the symbolnaming. So looking at performance (in a simple example) there is no issue.

    Now on the topic of pointers vs references. IMHO I think clearity stands above all. As soon as I read implicit behaviour my toes start to curl. I agree that it is nice implicit behaviour that a reference cannot be NULL.

    Dereferencing a NULL pointer is not the problem. it will crash your application and will be easy to debug. A bigger problem is uninitialized pointers containing invalid values. This will most likely result in memory corruption causing undefined behaviour without a clear origin.

    This is where I think references are much safer than pointers. And I agree with a previous statement, that the interface (which should be clearly documented, see design by contract, Bertrand Meyer) defines the result of the parameters to a function. Now taking this all into consideration my preferences go to using references wherever/whenever possible.

    0 讨论(0)
  • 2020-11-22 03:22

    My rule of thumb is:

    • Use pointers for outgoing or in/out parameters. So it can be seen that the value is going to be changed. (You must use &)
    • Use pointers if NULL parameter is acceptable value. (Make sure it's const if it's an incoming parameter)
    • Use references for incoming parameter if it cannot be NULL and is not a primitive type (const T&).
    • Use pointers or smart pointers when returning a newly created object.
    • Use pointers or smart pointers as struct or class members instead of references.
    • Use references for aliasing (eg. int &current = someArray[i])

    Regardless which one you use, don't forget to document your functions and the meaning of their parameters if they are not obvious.

    0 讨论(0)
  • 2020-11-22 03:22

    There is problem with "use references wherever possible" rule and it arises if you want to keep reference for further use. To illustrate this with example, imagine you have following classes.

    class SimCard
    {
        public:
            explicit SimCard(int id):
                m_id(id)
            {
            }
    
            int getId() const
            {
                return m_id;
            }
    
        private:
            int m_id;
    };
    
    class RefPhone
    {
        public:
            explicit RefPhone(const SimCard & card):
                m_card(card)
            {
            }
    
            int getSimId()
            {
                return m_card.getId();
            }
    
        private:
            const SimCard & m_card;
    };
    

    At first it may seem to be a good idea to have parameter in RefPhone(const SimCard & card) constructor passed by a reference, because it prevents passing wrong/null pointers to the constructor. It somehow encourages allocation of variables on stack and taking benefits from RAII.

    PtrPhone nullPhone(0);  //this will not happen that easily
    SimCard * cardPtr = new SimCard(666);  //evil pointer
    delete cardPtr;  //muahaha
    PtrPhone uninitPhone(cardPtr);  //this will not happen that easily
    

    But then temporaries come to destroy your happy world.

    RefPhone tempPhone(SimCard(666));   //evil temporary
    //function referring to destroyed object
    tempPhone.getSimId();    //this can happen
    

    So if you blindly stick to references you trade off possibility of passing invalid pointers for the possibility of storing references to destroyed objects, which has basically same effect.

    edit: Note that I sticked to the rule "Use reference wherever you can, pointers wherever you must. Avoid pointers until you can't." from the most upvoted and accepted answer (other answers also suggest so). Though it should be obvious, example is not to show that references as such are bad. They can be misused however, just like pointers and they can bring their own threats to the code.


    There are following differences between pointers and references.

    1. When it comes to passing variables, pass by reference looks like pass by value, but has pointer semantics (acts like pointer).
    2. Reference can not be directly initialized to 0 (null).
    3. Reference (reference, not referenced object) can not be modified (equivalent to "* const" pointer).
    4. const reference can accept temporary parameter.
    5. Local const references prolong the lifetime of temporary objects

    Taking those into account my current rules are as follows.

    • Use references for parameters that will be used locally within a function scope.
    • Use pointers when 0 (null) is acceptable parameter value or you need to store parameter for further use. If 0 (null) is acceptable I am adding "_n" suffix to parameter, use guarded pointer (like QPointer in Qt) or just document it. You can also use smart pointers. You have to be even more careful with shared pointers than with normal pointers (otherwise you can end up with by design memory leaks and responsibility mess).
    0 讨论(0)
  • 2020-11-22 03:23

    For pointers, you need them to point to something, so pointers cost memory space.

    For example a function that takes an integer pointer will not take the integer variable. So you will need to create a pointer for that first to pass on to the function.

    As for a reference, it will not cost memory. You have an integer variable, and you can pass it as a reference variable. That's it. You don't need to create a reference variable specially for it.

    0 讨论(0)
  • 2020-11-22 03:24

    Disclaimer: other than the fact that references cannot be NULL nor "rebound" (meaning thay can't change the object they're the alias of), it really comes down to a matter of taste, so I'm not going to say "this is better".

    That said, I disagree with your last statement in the post, in that I don't think the code loses clarity with references. In your example,

    add_one(&a);
    

    might be clearer than

    add_one(a);
    

    since you know that most likely the value of a is going to change. On the other hand though, the signature of the function

    void add_one(int* const n);
    

    is somewhat not clear either: is n going to be a single integer or an array? Sometimes you only have access to (poorly documentated) headers, and signatures like

    foo(int* const a, int b);
    

    are not easy to interpret at first sight.

    Imho, references are as good as pointers when no (re)allocation nor rebinding (in the sense explained before) is needed. Moreover, if a developer only uses pointers for arrays, functions signatures are somewhat less ambiguous. Not to mention the fact that operators syntax is way more readable with references.

    0 讨论(0)
  • 2020-11-22 03:26

    You properly written example should look like

    void add_one(int& n) { n += 1; }
    void add_one(int* const n)
    {
      if (n)
        *n += 1;
    }
    

    That's why references are preferable if possible ...

    0 讨论(0)
提交回复
热议问题