0

I want to make an object that can be given or provide it's own implementation of some pure virtual base class. This object would have complete ownership of this implementation, so taking an rvalue in the constructor seemed like a good fit:

 struct base_haver {
    base_haver() : base_haver(derived{}) {} // Provides default implementation
    base_haver(base && b) : mBase(b) {} // Caller provides implementation

    void call_func() { mBase.func(); }

    base & mBase;
};

However, given these dummy classes:

struct base {
    virtual void func() = 0;
};

struct derived : public base {
    virtual void func() override { }
};

I get an access violation exception when calling base_haver::call_func() after creating it with the parameterless constructor:

base_haver b;
b.call_func(); // <-- Access violation exception (this->mBase.**** was 0xFFFFFFFFFFFFFFFF)

But if I provide that same implementation I get no exception:

base_haver b(derived{}); // <-- Identical to default constructor
b.call_func(); // <-- No exception, works fine.

I found a similiar question at Take ownership of parameter by rvalue-reference, which seems to indicate I have the right idea. The difference in my case is that my member has to be a reference - since it's a pure virtual class my base_haver can only have a pointer or reference to it's implementation.

Am I misunderstanding something about rvalues? Why would the base_haver's default constructor cause base_haver::call_func() to result in an access violation exception?

Sark
  • 1
  • You are using an rvalue reference, which is distinct form an rvalue. Both examples are undefined behavior, you just got unlucky with the second that it didn't report an error. – François Andrieux Dec 14 '17 at 23:15
  • If you changed your program to [this example](https://www.ideone.com/wNw1ey), you will see that the `derived` object has long been destroyed before the constructor body is entered. – PaulMcKenzie Dec 14 '17 at 23:19
  • `mBase` is a dangling reference. – Kerrek SB Dec 14 '17 at 23:25
  • Thank you for the clarifications, I I will use a unique_ptr instead and leave the r-value references for when I have a better grasp on how to use them properly. – Sark Dec 15 '17 at 09:23
  • Think of an rvalue as a temporary result that will be destroyed very soon. You can't take a reference to it, you can only read/copy it. – Gem Taylor Dec 15 '17 at 11:25

0 Answers0