0

I have problem with initializing pointer to Bird in BirdHouse's constructor initialization list. It seems that it doesn't point to the object that I want to point to.

Here is the Bird class:

class Bird
{
    std::string name;
    static int objectCount;
public:
    Bird () : name("Bird #" + std::to_string(objectCount))
    {
        ++objectCount;
    }

    Bird (const Bird& bb) : name(bb.name + " copy")
    {
    }

    friend class BirdHouse;
};

And here is the BirdHouse class:

class BirdHouse
{
    Bird b;
    Bird * bp;
    Bird & br;
public:
    BirdHouse(Bird aa, Bird bb, Bird cc) : b(aa), bp(&bb), br(cc) {}

    void print() const
    {
        std::cout << "Bird b = " << b.name << std::endl;
        std::cout << "Bird * bp = " << bp->name << std::endl;
        std::cout << "Bird & br = " << br.name << std::endl;
    }
};

When I want to call BirdHouse::print() in main() the program crashes:

int main()
{
    Bird b1;
    Bird b2;
    Bird b3 = b2;

    BirdHouse bh1(b1,b2,b3);
//    bh1.print();    // I can't call it because b2 points to weird stuff

    return 0;
}

How should I initialize BirdHouse object so it points to appropriate Bird object?

0

4 Answers 4

4

The crash is because of undefined behavior, because you save a pointer to an argument that is passed by value, and that object will be destructed once the function returns.

There are two possible solutions as I can see it: Either pass the variable as a pointer to begin with, or pass it by reference. However, be careful because if the lifetime of the BirdHouse object is longer than the lifetime of the object you pass in (as a pointer or a reference) you will once again have undefined behavior.

Sign up to request clarification or add additional context in comments.

Comments

1
BirdHouse(Bird aa, Bird bb, Bird cc) : b(aa), bp(&bb), br(cc) {}

aa, bb and cc are parameters passed by values, which are local to your constructor. However, you store a pointer to bb and a reference to cc, which both become dangling when the constructor ends.

When you try to access one of the dangling members in print(), you trigger Undefined Behaviour, in your case a crash. Don't do that.

Turning up your compiler warnings will probably notify you about this problem.

Comments

1
BirdHouse(Bird aa, Bird bb, Bird cc) : b(aa), bp(&bb), br(cc) {}

Here you take argument by value, thus creating a copy. You then go on to store a pointer and reference to these copies which will be destructed at the end of the constructor. Now whenever you attempt to access these, you invoke undefined behaviour.

To fix this, you could take your arguments in by reference instead:

BirdHouse(Bird& aa, Bird& bb, Bird& cc) : b(aa), bp(&bb), br(cc) {}

Comments

1
BirdHouse(Bird aa, Bird bb, Bird cc) : b(aa), bp(&bb), br(cc) {}
//                 ^^^^^^^, this is a temporary object (i.e., it won't exist
//                          after the constructor completes

Above you take an address to a temporary parameter. If you tried to use bp in the body of the constructor. However, once the constructor completes the temporary object is gone but bp still points to that memory address. Finally, once the print function is executed it dereferences a pointer which no longer points to a valid object and the behavior is undefined.

Depending on your use case you could change your constructor to be:

A)

BirdHouse(Bird aa, Bird& bb, Bird& cc) : b(aa), bp(&bb), br(cc) {}

B)

BirdHouse(Bird aa, Bird* bb, Bird& cc) : b(aa), bp(bb), br(cc) {}

Note: It needs to be clear to the caller that the lifetimes of bb and br need to last at least as long as the lifetime of the BirdHouse instance.

2 Comments

Note that we do not know if there is an ownership transfer -- probably not, in the context of a bird house ;)
@Quentin Yes, I would agree that ownership wouldn't make sense in this case but I thought it was useful information in general but perhaps it just muddies the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.