views:

613

answers:

13

I am programming in C++ more then 5 years, and have never met any place where reference of the variable is recommended to use except as a function argument (if you don't want to copy what you pass as your function argument). So could someone point cases where C++ variable reference is recommended (I mean it gives any advantage) to use.

+1  A: 

I tend to agree, but perhaps const return values.

kenny
+3  A: 

I use references in function arguments not just to avoid copies but also instead of pointers to avoid having to deal with NULL pointers where appropriate. Pointers model a "maybe there's a value, but maybe not (NULL)", references are a clear statement that a value is required.

... and to make it absolutely clear (-> comments). I tend to avoid pointers to model "maybe there are several values" - a vector is a better option here. Pointers to several values often end up in C-style programming because you usually have to pass the # of elements as well separately.

Rüdiger Hanke
I agree that it is not possible to have a reference with NULL value but you can't use them insted of pointers. Pointers are really very different thing!
Narek
Pointers also model "may-be there are several values".
UncleBens
That's right, pointers have more uses than that. However, quite often people pass pointers simply for efficiency reasons. I should have added "where appropriate" above.
Rüdiger Hanke
Michael Krelin - hacker
You can, absolutely, but it's not legal, whereas passing NULL is, so while you can construct NULL references, the caller has the problem, not the function (IMHO).
Rüdiger Hanke
With "not legal", I mean "undefined behaviour".
Rüdiger Hanke
That's right. On the other hand, the same applies to pointers. Whenever you do not document behavior when passed NULL — you can say it's caller's responsibility to provide valid data.
Michael Krelin - hacker
Nay, that's not quite the same. When I use references, the intention is obvious ***from the type signature***. It's 2009, and I like to put as much information as possible into my type signatures.
Rüdiger Hanke
Half-obvious. Since using pointer doesn't imply that you welcome null-pointers, using reference does not add *much* (but certainly isn't equivalent either). But I think we're going too far in discussing the obvious, what I objected was the statement (not yours, see first comment here) that *it is not possible to have reference with NULL value*. And I think you agree with me on that.
Michael Krelin - hacker
It's really tiring me to constantly having to qualify the obvious, as in the original answer where I didn't mean to imply that I replace all sorts of points with references. The verbose version of my quote is, "you can't have NULL references in a C++ program that does not have undefined behaviour according to language specifications". See also http://www.gotw.ca/conv/002.htm. What I do not agree with is that a reference in a type signature is only half-obvious.
Rüdiger Hanke
@hacker - You could force a NULL reference if you really want to, but not if you like keeping your job. I can also call delete (int*)rand(); But it'd be stupid. If a function is receiving a reference, it's up to the caller to make sure that it's not passing in a dereferenced NULL. If the function is receiving a pointer, it's up to the function author to either handle NULLs, or document clearly that NULLs are not handled.
Eclipse
Rüdiger Hanke, have you tried to read and understand my last comment or do you find blind reply more entertaining?
Michael Krelin - hacker
Eclipse, the pointer part is wrong. If you're using a pointer and state that parameter `p` is supposed to be a pointer to buffer it doesn't imply you welcome `NULL`s. Unless you explicitly say so. You tend to overlook UncleBens' comment here. Pointer is not about making things optional.
Michael Krelin - hacker
Your buffer is a sequence of objects. Imagine it grouped in a vector and you're back with optional semantics: you have a sequence of objects or not. When I need buffers, I prefer to take iterators. I know that pointers can be iterators and pointers can again be NULL, but at least requirements on iterators are well understood and no STL function I can think of now takes "invalid" iterators, so this is my favoured resolution in this case even though C++ is admittedly weak here. It's about being "as precise as possible" in the type signature and reuse of known concepts to aid the caller.
Rüdiger Hanke
+5  A: 

I tend to use reference members instead of pointers for externally controlled non-optional construction parameters.

EDIT (added example):

Let's say that you have a database and a DAO class having the database as a dependency:

struct Database {};
struct PersonDao {
    const Database &m_d;
    PersonDao(const Database &d): m_d(d) {}
};

Furthermore, the scope of the database is controlled externally from the DAO:

int main() {
    Database d;
    PersonDao pd(d);
}

In this case it makes sense to use a reference type, since you don't ever want DAO::m_d to be null, and its lifetime is controlled externally (from the main function in this case).

disown
Would you please give an example?Thanks.
pierr
No problem, done.
disown
Well, you can always `PersonDao *badboy() { Database d; return new PersonDao(d); }`
Michael Krelin - hacker
I would classify that as a more general problem with manual memory management, not a reason not to use references. Besides, you would have exactly the same situation with a pointer, so what is your point?
disown
disown, it is *not* the reason *not* to use references. And yes, you got my point and voiced it all right — you have exactly the same situation with a pointer ;-)
Michael Krelin - hacker
+12  A: 

As a return value of an opaque collection accessor/mutator

The operator[] of std::map returns a reference.


To shorten the text needed to reference a variable

If you miss old-school with Foo do ... statement (that's Pascal syntax), you can write

 MyString &name = a->very->long_->accessor->to->member;
 if (name.upcase() == "JOHN") {
    name += " Smith";
 }

another example of this can be found in Mike Dunlavey's answer


To state that something is just a reference

References are also useful in wrapper objects and functors--i.e. in intermediate objects that logically contact no members but only references to them.

Example:

class User_Filter{
  std::list<User> const& stop_list;
  public: Functor (std::list<User> const& lst)
    : stop_list(lst) { }
  public: bool operator()(User const& u) const
    {  return stop_list.exists(u); }
};

find_if(x.begin(),x.end(),User_Filter(user_list));

The idea here that it's a compile error if you don't initialize a reference in constructor of such an object. The more checks in compile time--the better programs are.

Pavel Shved
+1  A: 

Well you kind of have two choices for aliasing other values(ignoring shared_ptrs and the like): pointers and references.

References must be initialized at construction to refer to something else. So semantically a reference can never be NULL. In reality, though, the underlying data can go away, giving you problems often more difficult to debug than if a pointer went away. So I'm not sure there's a real advantage here unless you were disciplined and consistent with how they were used vis-a-vis referring to items that were dynamically allocated. If you did this with pointers too, you'd avoid the same problems.

Perhaps more importantly, references can be used without thinking about all the issues that arise with pointers. This is probably the main advantage. Semantically a reference is the thing. If you guarantee as the caller/callee that the underlying memory doesn't go away, you don't have to confuse the user with any of the questions that come along with pointers (Do I need to free this? Could this be NULL? etc) and can safely use a reference for convenience.

An example of this might be a function that looks up the corresponding string for an enum,

const std::string& ConvertToString( someEnum val)
{
   static std::vector< std::string > lookupTable;
   if (lookupTable.empty())
   {
      // fill in lookup table
   }
   // ignoring the cast that would need to happen
   return lookupTable[val]
}

Here the contract between the caller and the callee guarantees that the return type will always be there. You can safely return a reference, and avoid some of the questions that pointers invite.

Doug T.
Debugging with references and pointers is not different at any rate. As long as you keep in mind that a reference is _not_ the referred object but an alias it is not different than a pointer.
David Rodríguez - dribeas
+11  A: 

Here's a case where it's handy:

MyClass myArray[N];

for (int i = 0; i < N; i++){
    MyClass& a = myArray[i];
    // in code here, use a instead of myArray[i], i.e.
    a.Member = Value;
}
Mike Dunlavey
That is to say except what I have mentioned it is being used for aliasing only. :-)
Narek
@Narek: Hunh ??
Mike Dunlavey
+1  A: 

References make code prettier. So use them whenever it takes a reference to beautify your code.

Michael Krelin - hacker
A: 

i would like to enlist some cases:

1) while writing singleton classes

 class singleton
    {
        singleton();
        explicit singleton(const singleton&);
        singleton& operator=(const singleton&);
    public:
        static singleton& instance()
        {
         static singleton inst;
         return inst;
        }
    };// this is called the 'Meyers' singleton pattern. refer to More Effective C++ by  Scott Meyers

it has all the benefits, but avoids using the new operator

2)here is no such thing as a null reference. A reference must always refer to some object. As a result, if you have a variable whose purpose is to refer to another object, but it is possible that there might not be an object to refer to, you should make the variable a pointer, because then you can set it to null. On the other hand, if the variable must always refer to an object, i.e., if your design does not allow for the possibility that the variable is null, you should probably make the variable a reference

3)Because a reference must refer to an object, C++ requires that references be initialized:

  string& rs;             // error! References must
                          // be initialized

  string s("xyzzy");

  string& rs = s;         // okay, rs refers to s

Pointers are subject to no such restriction

The fact that there is no such thing as a null reference implies that it can be more efficient to use references than to use pointers. That's because there's no need to test the validity of a reference before using it

4)Another important difference between pointers and references is that pointers may be reassigned to refer to different objects. A reference, however, always refers to the object with which it is initialized: ¤ Item M1, P10

  string s1("Nancy");
  string s2("Clancy");

  string& rs = s1;         // rs refers to s1

  string *ps = &s1;        // ps points to s1

  rs = s2;                 // rs still refers to s1,
                           // but s1's value is now
                           // "Clancy"

  ps = &s2;                // ps now points to s2;
                           // s1 is unchanged
sat
i was expecting comments from who don not agree :(
sat
A: 

I've used a reference to an ostream instead of a pointer. I supppose that I prefer references to pointers when the class has a lot of operators.

KitsuneYMG
+2  A: 

Use a const reference to give a name to a value, e.g.:

const Vec3 &ba=b-a;

This names the value, but doesn't necessarily create a variable for it. In theory, this gives the compiler more leeway and may allow it to avoid some copy constructor calls.

(Related non-duplicated Stack Overflow question at http://stackoverflow.com/questions/760578/const-reference-to-temporary. The Herb Sutter link there has more information about this.)

brone
Interesting, had no idea you could do that.
Viktor Sehr
Hah, tricky! Didn't know this. :-)
Frerich Raabe
+2  A: 

The argument to the copy-constructor MUST be passed as a reference, since otherwise the copy constructor would need to call it self in an endless recursion (stack overflow).

ragnarius
+1  A: 

Stream operators are an obvious example

std::ostream & operator<< (std::ostream &, MyClass const &...) {
  ....
}

mystream << myClassVariable;

You obviously don't want a pointer as checking for NULL makes using an operator very tedious i.s.o. convenient

Pieter
+4  A: 

Use references wherever you want, pointers when you are forced to.

References and pointers share part of their semantics: they are an alias to an element that is not present. The main difference is with memory managements: references express clearly that you are not responsible for the resource. On the other hand, with pointers it is never really clear (unless you mean smart pointers): are you assumed to delete the pointer or will it be deleted externally?

You must use pointers when you must manage memory, want to allow for optional semantics or need to change the element referred to at a later time.

In the rest of cases, where you can use a reference or a pointer, references are clearer and should be preferred.

Now, as you point out, they are really not needed: you can always use pointers for all the reference uses (even parameter passing), but the fact that you can use a single tool for everything does not mean there are no better suited tools for the job.

David Rodríguez - dribeas
I completely agree with your reasoning, but just wanted to add that just for optional semantics you can also use boost::optional http://www.boost.org/doc/libs/1_40_0/libs/optional/doc/html/index.html
Pieter