I have an abstract class Base
and derived class Derived
:
class Base
{
public:
Base(int n) :_n(n) { _arr = new int[n]; }
virtual ~Base() { delete[] _arr; }
Base(Base&& other) { _n = other._n; _arr = other._arr; other._arr = nullptr; other._n = 0; }
virtual void func() = 0;
private:
int _n;
int* _arr;
};
class Derived : public Base
{
public:
Derived(int m, int n) : Base(n), _m(m) { _arr = new int[m]; }
~Derived() { delete[] _arr; }
Derived(Derived&& other) : Base(std::move(other)) { _m = other._m; _arr = other._arr; other._arr = nullptr; other._m = 0; }
void func() override { cout << "func"; }
private:
int _m;
int* _arr;
};
Then I have a class Bag
which contains a rvalue reference of Base
:
class Bag
{
public:
Bag(Base&& b) : _b(std::move(b)) {}
void func() { _b.func(); }
private:
Base&& _b;
};
int main()
{
Bag bag(Derived(1, 1));
bag.func();
}
I use a rvalue reference member _b
because I just want to take a temporary object in Bag
's constructor. However, after bag.func()
I got an error: abort() is called. It seems that bag._b
's type changes from Derived
to Base
after the temporary object Derived(1,1)
is destructed.
bag.func()
works after I delete virtual ~Base() { delete[] _arr; }
. Why? If I need Base
's destructor, how can I change my code?
CodePudding user response:
Base&& _b
is a reference to the temporary object, when that temporary is destroyed at the end of the line Bag bag(Derived(1, 1));
the reference becomes a dangling reference and any use of the reference is undefined behaviour.
You could change _b
to a value instead but that would slice your object.
If you want to store a polymorphic object the only real option is to use a pointer (ideally a smart one). For example:
class Bag
{
public:
Bag(std::unique_ptr<Base>&& b) : _b(std::move(b)) {}
void func() { _b->func(); }
private:
std::unique_ptr<Base> _b;
};
int main()
{
Bag bag(std::make_unique<Derived>(1, 1));
bag.func();
}
Note that you should also ensure that Base
and Derived
follow the rule of five otherwise you may encounter issues when you assign objects.