5

I need one clarification in c++ linux.

I have class C1 and another class C2. C1 will have the reference of C2.

class C1
{

   C2 &obj ;

}

i am thinking of two choices here ,

  1. Directly holding the reference of C2 as C2 &obj;
  2. Creating the pointer of C2, as c2* obj;

Which is good ? what is the difference in it ? when choose either?

Alok Save
  • 202,538
  • 53
  • 430
  • 533
Muthu
  • 107
  • 1
  • 8

4 Answers4

2

Avoid using a reference member as much as possible.

The same differences as that of references and pointers apply here,
If you have a reference member then it must be initialized at the time of creation of your class object you cannot have a lazy initialization as in case of pointer member because references cannot be NULL and cannot be reseated, while a pointer member can be made to point to a C2 instance lazily as and when required.

Also, note that there are other side effects as well, Once you have a reference member the compiler will not generate the copy assignment operator(=) & You will have to provide one yourself, It is cubersome to determine what action your = operator shall take in such a case.

For most practical purposes(unless you are really concerned of high memory usage due to C2 size) just holding an instance of C2 as member of C1 should suffice, instead of pointer or reference member, that saves you a whole lot of worrying about other problems which reference/pointer members bring along though at expense of extra memory usage.

If you must, use a pointer make sure you use a smart pointer instead of a raw pointer, that would make your life much easier with pointers.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • For the exact reasons you mentioned, using a pointer is preferable to using a reference as a member. Using a reference is a less general solution and may result in surprising behaviour. I would suggest to always avoid using a reference as a member. – Maxim Egorushkin Mar 05 '12 at 07:54
  • I'd add that there are cases when the limitations of a reference fit exactly what you're trying to describe with your code, i.e. an object which is associated with another object for its whole lifetime (like a mutex lock object with a mutex object, for instance). In such cases using a reference is more explicit. – Kos Mar 05 '12 at 11:34
0

a pointer has two main advantages to references. the pointer can be null and a pointer can be moved (with ++ operator for example). The moving doesn't help you here. If your class C2 is not known when you instantiate C1 then you should use a pointer because you have no way to initialize the reference, but the pointer can be initialized to null.

Like Als said, i would also recommend using pointers when the C2 instance may change. You can uses references in this case but i think pointers are a 'cleaner' solution.

D-rk
  • 5,513
  • 1
  • 37
  • 55
0

Neither is good. If you have any pointer or reference member variable pointing at something allocated outside your class, it most likely means that the program design is flawed somehow.

One case I can come up with where it is justified, is when you have some sort of peculiar, external garbage collector functionality. (For example C++ Builder's automatic allocation/deallocation of VCL components on the heap.)

Another case is where it could be valid, is when you are emulating a C struct with a C++ class, or when writing a private class inside another class.

But then most likely, the need to point at something outside the class comes from flawed program design. I would think twice of why my code needs to do this, and at the very least try to add as much const correctness at possible to the pointer, ie const *c2 const obj;

If you have peculiar member pointers like this, you must also most likely manually write a copy constructor, assignment operator and destructor for your class.

Edit: The rationale for why this is bad practice is the concept called private encapsulation, which is one of the cornerstones of the program design concept called object-oriented design.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • "the need to point at something outside the class comes from flawed program design". I disagree, strongly. – J.N. Mar 05 '12 at 08:15
  • 1
    Do you really mean to say that any program which uses a graph is poorly designed? That using pointers for navigation is poorly designed? I'd argue almost the opposite: if you allocate something within the class, it's often more appropriate to make the object itself a member. Pointers are reserved for things allocated outside the class. – James Kanze Mar 05 '12 at 08:46
  • @JamesKanze What is a "graph"? That could mean anything, though I assume you mean the typical ADT called "graph". For that example, all nodes (vertices) of the graph should be allocated inside the graph class. The node class can expose pointers to the graph class, if declared as a private sub class of the graph. The user shouldn't need to concern themselves with raw pointers, they should navigate the graph through public member functions. – Lundin Mar 05 '12 at 10:32
  • A graph can be any case where objects refer to other objects (and back). There isn't necessarily a graph class; in fact, there typically isn't a graph class. And using public member functions doesn't solve anything; if you're going to navigate between objects, then the object you're going from must contain a pointer to the object you're going to (or to some other object which contains a pointer to the object you're going to). – James Kanze Mar 05 '12 at 11:21
  • @JamesKanze The caller would expect functions like next(), previous(), up(), down() or whatever. Why would the caller care which address the objects are allocated at? An example from the real world, a linked list class I've made. The node object has "next" and "prev" pointers that are exposed with public, but the node class is a private class of the linked list. Public member functions will have names like "add", "remove", "find", "change", "traverse". Thus there is no need for the caller to navigate between objects. In fact the caller couldn't care less of how the class is implemented. – Lundin Mar 05 '12 at 12:03
  • @J.N. How interesting. Your subjective opinion, without any rational arguments provided, is of great interest and benefit to the community. – Lundin Mar 05 '12 at 12:06
  • @Lundin : you didn't provide **any** argument to explain why it was bad design either, do your part first. – J.N. Mar 05 '12 at 12:26
  • @J.N. Alright, I assumed every C++ programmer implicitly understood why. Post updated. – Lundin Mar 05 '12 at 12:41
  • @Lundin : none of the two links explain why classes can't have members that are pointers to something not in the class. – J.N. Mar 05 '12 at 12:58
  • @Lundin Certainly. Nobody is arguing for _public_ pointer members. But functions like `next`, etc. will return pointers, which are copies of private member variables. For that matter, there aren't necessarily any such public functions: in patterns like Observer or Decorator, the object uses the pointer internally, without ever exposing it to outside. – James Kanze Mar 05 '12 at 13:09
  • @J.N. Private encapsulation goes both ways. Classes should be autonomous and not concern themselves with intimate details of other classes. A pointer is a direct access to a memory cell. Why should one class dig around in the internal memory of another class, or expose its own internal memory? If you are thinking that pass-by-reference equals better performance, that's likely pre-mature optimization on modern C++ compilers. They can optimize such things quite well. – Lundin Mar 05 '12 at 13:58
  • @JamesKanze Why would it return a pointer? Nobody is interested in that address outside the class. Such functions should return by value. For example, think of std::vector or similar. Why would you be interested in the address of item number 5 on the vector? It is some obscure heap address that might not even be valid once the vector is changed. The only reason you would ever want that address, is because you want to modify the contents. The proper OO way to do that is not to hand out the address, but to let the caller access the object through public setter/getter functions. – Lundin Mar 05 '12 at 14:07
  • @Lundin What should it return instead of a pointer? It can't return the object, since the object has identity, and isn't copyable, and is polymorphic. It could possibly return a reference, but there are cases where it must be able to return a null pointer as well; it somehow feels more natural for it to return a pointer. You seem to be confounding pointer with address; that may be the implementation, but what the coder sees is a unique id which allows access to a specific object (and no other). And that's pretty essential for many widely used patterns. – James Kanze Mar 05 '12 at 14:15
  • @Lundin a pointer (or reference) to another object is an access to its public parts **only**. It doesn't violate encapsulation at all. What does violate encapsulation is to downcast a pointer to `char*` and offset it to access private members. – J.N. Mar 05 '12 at 14:18
  • @Lundin Also, of course, objects to which you have pointers are almost always dynamically allocated. (There are a few cases where the pointers point to static objects.) You don't have vectors of such objects (you can't, since they aren't copyable), although you might have vectors of pointers to such objects. (And setter/getters in the strict sense are usually a sign of poor OO design.) – James Kanze Mar 05 '12 at 14:18
0

Which one you are going to use, depends on what you exactly need.

For example, you can use a reference member variable if you need some kind of dependency injection. Even then, you can use pointers. However, keep in mind that classes with reference members should generally be non-copyable.

In most cases, you should either use pointers or value member variables.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • 2
    References make the object non-assignable, but it can still be copied. (But I agree with your basic point: most of the time, prefer pointers to references in class types. Unless the type is already noncopyable.) – James Kanze Mar 05 '12 at 08:43
  • @JamesKanze Yes. Nicely said. My idea about non-copyable is that the class inherits from boost::noncopyable. In that case it is also non-assignable. But you got the point what I meant to say – BЈовић Mar 05 '12 at 08:49