tags:

views:

157

answers:

6

Hi all, this snippet of code is given me headache. Personally, I would like to use reference as they are neater compared to pointer, so I tried this:

include "SomeClass.h"

class FooBar 
{
   private:
     SomeClass& member_;

   public:
     FooBar() : member_(SomeClass()) { };
}

I have read that you need to assign a temp variable to a class member reference, so in this case I create a dummy SomeClass() (I'm not sure if I am doing it right here. I tried it with and without specifying a default constructor). However, it does not compile in VS 2005, saying that member_ cannot be initialised.

How should I be doing this? Thanks in advance!

+1  A: 

Do you definitely not want the reference to be set in the constructor? i.e.

FooBar(SomeClass& sc) : member_(sc) {};

If not, and you are going to set it later, then I think a pointer is your best option, despite not being as "neat".

See here.

William
Thanks for the link; I understand it now.
Extrakun
+3  A: 

You can only bind a temp to a const reference. So if you change it to

const SomeClass& member_;

you'll be fine.

You probably don't want this, though; you either should just declare member_ as a value, not reference, or, if you want it as a reference, you probably want to pass in a reference to your constructor, like

FooBar(SomeClass& sc) : member_(sc) { };
Jesse Beder
+1  A: 

1) References can not be changed to point to another object after it is initialized.

Do you really need this behavior?

2) When you initialize reference with temporary object, after this temp. object is out of scope your reference is invalid.

That's why your code is incorrect. And you have useless member now. I'd recommend to think about two alternatives

a) Consider using pointer instead of reference.

b) Change you constructor to something like this:

MyClass(type & a):membmer_(a){...}
inazaruk
I have completely forgot about references not being able to "point" to another object once initialized. Thanks
Extrakun
+1  A: 

Does this member need to be a pointer or a reference? Though your interface may be simplified, it doesn't look like you intend to pass an instance of SomeClass to the constructor of FooBar. This is where the reference is useful as you guarantee that the instance used by the class is the same as the one given to it.

If your intent is to encapsulate SomeClass in FooBar, then the following will suffice.

include "SomeClass.h"

class FooBar 
{
  private:
    SomeClass member_;

  // ... rest of your implementation ...
  // default ctor/dtor is sufficient.
}

This code will instantiate a SomeClass instance when FooBar is instantiated. The class destructor (generated by the compiler) will take care of releasing the stack memory that is allocated for member_.

Steve Guidi
The reason is I was expecting to pass in SomeClass later after Foobar is created, and I totally forgot about that it is not possible to change what a reference refers to once initialised. Thanks!
Extrakun
+1  A: 

According to the standard you can not store a non-const reference to a temporary variable. When you create SomeClass() object in the constructor it is a temporary object and you are trying to store it as a non-const reference. BTW, I don't think references are required here. You can simply store it as SomeClass member_;

Naveen
+1  A: 

Short answer: As Jesse pointed out, you probably want to use a value member or a pointer, but not a reference in this specific example.

Long answer: The memory model of C++ is more like C's and less like Java's. Objects can exist

  • on the stack. This is the case for parameters and local variables.
  • on the heap. This is the case for all objects created with new.
  • in the data segment. These are your global variables.
  • inside other objects as value members.

As opposed to this, in Java, except for primitive types and pointers (in Java called references), all objects are created with new and exist on the stack. This simpler memory model is sufficient for Java since it has garbage collector, which automatically destroys unused objects.

Standard C++ does not have a garbage collector. An object is deleted in the following circumstances:

  • a stack-based object is deleted when "it goes out of scope",
  • a global object is deleted when the application terminates,
  • objects contained in other objects are deleted when the containing object is deleted, but
  • objects on the heap must be manually deleted by the developer using delete.

Because this manual memory management is error prone, you usually define strong ownership policies between the objects in your C++-application.

Coming back to your question, you want to make sure that you can access your member_ as long as your FooBar-object exists. So if member_ is not something like FooBar's owner or another in a similar way closely related object, which is guaranteed to exist as long as the FooBar-object exists, you probably do not want to use a reference.

In your example, I would use

  • a value member if I think of FooBar containing member_,
  • a pointer otherwise.
Tobias