1

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();
Walter
  • 44,150
  • 20
  • 113
  • 196

1 Answers1

1

As this link points out, it is safe and not UB to delete this in a method, even if it is a bit confusing.

Is it safe to `delete this`?

I don't think the extra copying is an issue. To be sure you would have to profile. Absent profiling info, if it were me I would prefer second approach to first b/c it's simpler for the programmer to understand, but it's largely opinion.

You might also want to look into the shared_from_this template in C++11, if you want to make it simpler for objects to manipulate shared pointers to themselves and such.

Community
  • 1
  • 1
Chris Beck
  • 15,614
  • 4
  • 51
  • 87
  • thanks for reminding me of `shared_from_this`. – Walter Sep 07 '15 at 16:46
  • Please have a look at my edited question, i.e. the code using `shared_from_this` -- is this how one should use it? – Walter Sep 07 '15 at 16:54
  • sure, I guess even more simply it could be `if (some_condition) { return std::make_shared(); } else { return shared_from_this(); }` – Chris Beck Sep 07 '15 at 16:57