consider the following code
struct base {
virtual void bar(std::shared_ptr<base>&) = 0;
};
struct foo1 : base { /* ... */ };
struct foo2 : base {
void bar(std::shared_ptr<base>&obj)
{
// ...
if(some_condition)
obj = std::make_shared<foo1>(); // re-assign obj
// ...
}
};
std::shared_ptr<base> x = std::make_shared<foo2>();
x->bar(x); // last line
Does this code envoke UB? (note: the re-assigning of obj will destroy the this object of call foo2::bar when called from the last line). If no data of bar are accessed thereafter, is the code still okay?
An alternative way of coding this would be
struct base {
virtual std::shared_ptr<base> bar(std::shared_ptr<base>) = 0;
};
struct foo1 : base { /* ... */ };
struct foo2 : base {
std::shared_ptr<base> bar(std::shared_ptr<base> obj)
{
// ...
if(some_condition)
obj = std::make_shared<foo1>();
// ...
return obj;
}
};
std::shared_ptr<base> x = std::make_shared<foo2>();
x=x->bar(x);
which should be safe in any case, shouldn't it? Is the extra copying in this code a performance issue?
edit. After Chris answer, I had a look at shared_from_this, which allows the following alternative implementation
struct base : std::enable_shared_from_this<base> {
virtual std::shared_ptr<base> bar() = 0;
};
struct foo1 : base { /* ... */ };
struct foo2 : base {
std::shared_ptr<base> bar()
{
auto obj = shared_from_this();
if(some_condition)
obj = std::make_shared<foo1>();
// ...
return obj;
}
};
std::shared_ptr<base> x = std::make_shared<foo2>();
x=x->bar();