6

I have this code, but it is not a practical example.

Ex.

class Animal
{
   int i;
   int& ref;
   public:
   Animal() : ref(i)
   {
   }
};

Can anyone provide a real life example where ref is required as a class member so that I can understand it better?

user966379
  • 2,823
  • 3
  • 24
  • 30
  • 1
    @pst: That's totally irrelevant. C++ references cannot be rebound, so giving example uses of rebindable references adds nothing. – Ben Voigt Dec 17 '11 at 05:41
  • @BenVoigt Not *totally* irrelevant (most of the types I create avoid mutations/have "readonly" members). You do have a very valid point though. –  Dec 17 '11 at 05:49
  • @user966379, I think you need to rephrase you question as "What is the purpose of having a class member that is a ref type referring to another member in the same class?" This will help web searchers in future. – Murali Krishna Dec 17 '11 at 06:55

3 Answers3

3

Any time that multiple objects of some class A all need to refer to a single shared instance of the same or some other class; for example, several People can all have the same mother and/or father:

class Person {
    private:
      Person &mother_;
      Person &father_;

    public:
      Person(Person &mother, Person &father) : mother_(mother), father_(father) {}
      // ...
}
Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
  • 3
    For the OP's benefit, this is referred to as aggregation, which is commonly used in object-oriented programming. – Chris Parton Dec 17 '11 at 03:58
  • @ChrisParton I would not consider this "aggregation". When I think about "aggregation" in an OO context I think of using it as a form of type-extension that doesn't use inheritance -- e.g. methods to the "aggregating" object are proxied into internal/private objects (that are "being aggregated"). In this case, it's just a matter of *not* creating new objects but, rather, referring to the same "shared" objects. (A Person does not "extend" a mother Person or a father Person.) –  Dec 17 '11 at 04:41
  • 1
    That doesn't explain why you would use a *reference* rather than a pointer, since references cannot be rebound and pointers can. By using a reference, you ensure that you have to have a copy constructor. – Nicol Bolas Dec 17 '11 at 05:48
  • 1
    @PST: I believe that the concept of aggregation encompasses more than your description. To my knowledge, aggregation is simply a variation on composition in which the lifetime of the aggregated object is not dictated by the lifetime of the containing object. For instance, if a `Person` is destroyed, their `mother` and `father` are not (a rather morbid example, I know). In a composition relationship, this would not be the case. Wikipedia seems to agree: [http://en.wikipedia.org/wiki/Object_composition#Aggregation](http://en.wikipedia.org/wiki/Object_composition#Aggregation). – Chris Parton Dec 17 '11 at 06:08
  • The example does not mention a reference variable referring to a member in the same class. Or, did I understand it wrongly? – Murali Krishna Dec 17 '11 at 06:31
  • @ChrisParton Thanks for the link, and well-defended :) –  Dec 17 '11 at 07:26
  • @pst: No worries, I'm fresh out of my second year of a computer science degree, so this stuff is still firmly embedded in my brain haha. – Chris Parton Dec 17 '11 at 07:55
  • @MuraliKrishna -- As far as I can tell, that's not a salient feature of the original post, it's a subtlety that's been pointed out in comments by other people. If that's the real question, then I think the best answer would be *no*; I can't think of a reason when such a thing would ever make sense. – Ernest Friedman-Hill Dec 17 '11 at 13:42
1

Sure: The whole purpose of the template class std::reference_wrapper<T> is to hold a reference!

This has many uses. For example, you can pass it to the std::thread constructor (which always makes copies). You can also make containers of reference-wrappers.

Holding a reference to something might also be useful when you want to wrap an output stream; you hold the original stream as a reference and add things to it (for example, this answer of mine could be improved by adding a reference to the underlying stream to the wrapper objects).

Community
  • 1
  • 1
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
1

It's fundamentally the same as a const pointer. If you need a non-null pointer to some other object, and that pointer will only be assigned during construction, you may choose to use a reference instead.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720