I have a class Holder with a vector that holds instances of different classes (e.g. Derived) derived from the same abstract base class (Base). I constructed it as a vector of pointers to the base class to support polymorphism. New instances are added to the vector via a method called add. The new classes are constructed inside the parentheses when calling add and are not named (this mechanism is supplied to me and cannot be changed).
I do not quite understand what the lifetime of this constructed class is and how can I prevent it from being destructed right after exiting add. It has to be constructed, so is there a way to keep it alive and hold a valid pointer to it? Or will I have to create a copy and let the passed temporary die?
I am using C++17, none of my classes allocate memory manually, only STL containers and primitive data types are used. I've been looking at std::move() but I did not find what I needed. Example code:
class Base
{
public:
std::vector<int> vec;
virtual void foo() = 0;
}
class Derived : public Base
{
public:
Derived(int a, int b)
{
vec.push_back(a);
vec.push_back(b);
}
void foo() override;
}
class Holder
{
public:
std::vector<Base*> ptrs;
void add(Base& arg) // What should be the type of arg? (Does not have to be Base&)
{
ptrs.push_back(&arg); // How should I add a pointer to arg into ptrs so that
// arg stays alive after returning from this method?
}
}
int main()
{
Holder h;
h.add(Derived(1, 2)); // this is how add() gets called, I cannot change it
...
}
EDIT: To clarify, I can change the signature and body of add as well as the data type that vector ptrs uses. I cannot change the way add is called (h.add(Derived(1, 2));).
In
mainthe parameter passed is a temporary destroyed just after the call to
addreturns. You may store this value, the address, but you must never dereference it.If you want to ensure the the object remains valid for the lifetime of
Holderyour only option is taking over the ownership of an existing object or making a copy you've got ownership of.Taking ownership of an existing object
For this using
std::unique_ptrwould be preferrable to make the ownership clear.Making a copy
Use the move constructor here to void a copy
EDIT
According to the updated answer this is the implementation of
HolderI'd go with:Note: This only works with a virtual destructor of
Base; if this isn't an option, you'll need to save logic for invoking the correct destructor alongside the object. You do not prevent the creation of the temporaryDerivedobject, but at least it's possible to use the implicitly created move constructor ofDerivedto prevent unnecessary copies of the elements ofBase::vec