0

I'm fairly new to Pass By Reference, and I HAVE to make sure I understand this correctly. I have to convert all my Heap memory to Stack memory because my professor said so, and I'm stuck on two concepts.

What is the best way to store a reference in a class? I originally had member objects as non pointers, but noticed the deconstructor would be called on the member variable when the object (not member object) was popped off the stack. This makes me think it was a copy, and not actually a reference.

Here is an example of what I had originally:

class B
{
    public:
        B();
        ~B();
};

class A
{
    private:
        B b;
    public:
        A();
        ~A();
        setB(B& bVar);
};

void A::setB(B& bVar)
{
    b = bVar;
}

My solution was to change it to a pointer so it didn't call the deconstructor, but I'M NOT SURE IF THIS IS THE CORRECT WAY TO DO IT. Here was my solution:

class B
{
    public:
        B();
        ~B();
};

class A
{
    private:
        B* b;
    public:
        A();
        ~A();
        setB(B& bVar);
};

void A::setB(B& bVar)
{
    b = &bVar;
}

My second question is kind of related. I'm not sure what exactly happens when you have:

object1 = object2&. 

Is object1 a copy or is it actually another identifier for object2?

Taztingo
  • 1,915
  • 2
  • 27
  • 42
  • 1
    It is correct way to do it. But you have to take care of freeing the memory. I am not sure for the second part. Does it compile? – Aman Deep Gautam Nov 14 '13 at 10:08
  • The strange part is why you think calling the destructor is a bad idea. If your objects can't be freely copied and destroyed then your code is bugged. – john Nov 14 '13 at 10:09
  • I don't want the deconstructor called on the member object because it is pass by reference. It ends up with a double delete. – Taztingo Nov 14 '13 at 10:11
  • 2
    @user1932934 Exactly, your code is bugged. You should improve your code so objects can be copied. You probably need to write (or rewrite) your copy constructor and assignment operator. Have a look here http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three . The link describes the easy way to write C++, what you're trying now is the hard way, – john Nov 14 '13 at 10:12
  • `object1 = object2&` isn't actually valid C++. – juanchopanza Nov 14 '13 at 10:15
  • The modern C++ way is to pass by value and then move `bVar` into `b`. – kennytm Nov 14 '13 at 10:16
  • I'm sorry for making that confusing. What I meant by the second part is what I have for setB in the first example I showed. I will take a look at the posted link. – Taztingo Nov 14 '13 at 10:16
  • 1
    @user1932934 Since you're not storing a reference, only passing one, two different objects are destroyed. There is no "double delete". – molbdnilo Nov 14 '13 at 10:16

1 Answers1

3

References behave like symbolic aliases to instances, and are in some respects like "pointers" that can't (shouldn't) be null. For the sake of this explanation, I'll refer to them below as though they were pointers.

When you have a T&, it means that it is pointing to a T, and is not itself a copy.

When you have a T = T&, it means you'll get a copy (or a copy of a copy) depending on how the constructor or assignment operator are defined.

When you have an R& = L, it means you'll get copy of L into whatever the R& is pointing to (provided the assignment operator of R permits this).

Concerning the "correct" way of storing references, I would ask at least these questions:

  • Is it acceptable for the member reference to remain the same throughout the containing object's lifetime?
  • Will instances of the containing type always be destroyed before the object(s) pointed to by the member reference?

If both are true, then simply declaring and appropriately initializing a member T& should suffice:

class B
{
    // details...
};

class A
{
    B &_b;
public:

    A(B &b) :
    _b(b)
    {}
};

Otherwise, despite the requirements imposed upon you, the situation might call for something like shared_ptr<> or similar.

References to objects living on the stack, in-turn held by other objects that themselves may be constructed in such a way that they will outlive their reference's lifespan are merely pointers waiting to dangle.

Consider copying, or arguing that heap-allocated memory is the better option.

If you are uncertain of the reference network induced by your program, you need to redesign it.

EDIT:

It is important to note that, when passing a reference to a function (const T& in particular), there are certain situations in which it can be elided by the compiler. For example: When such a function is inlined, references can be replaced by more efficient addressing logic than if they were required to be pointers.

In this respect, they are not pointers.

defube
  • 2,395
  • 1
  • 22
  • 34
  • 3
    Put simply, references are aliases to another object. They are _not_ pointers (although they will be implemented as pointers in certain cases). – James Kanze Nov 14 '13 at 10:36
  • 1
    References are aliases to other objects, they are initialised once on declaration and from that moment act as though they are the object, they cannot be reassigned to alias another object, and cannot be null. (Though it is possible to initialise a reference by dereferencing a null pointer. This is a bad idea.) – Grimm The Opiner Nov 14 '13 at 10:56
  • I know this. My wording is once again lacking, so I've updated my answer. – defube Nov 14 '13 at 11:31