【问题标题】:re-assigning shared_ptr from within object pointed to [duplicate]从指向[重复]的对象内重新分配shared_ptr
【发布时间】:2015-09-07 16:28:41
【问题描述】:

考虑下面的代码

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

这段代码会唤起 UB 吗? (注意:从最后一行调用时,重新分配 obj 将破坏调用 foo2::barthis 对象)。如果之后没有访问bar的数据,代码还可以吗?

另一种编码方式是

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);

在任何情况下都应该是安全的,不是吗?此代码中的额外复制是否存在性能问题?


编辑。克里斯回答后,我查看了shared_from_this,它允许以下替代实现

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();

【问题讨论】:

    标签: c++ shared-ptr self-reference


    【解决方案1】:

    正如这个链接所指出的,在一个方法中,delete this 是安全的,而不是 UB,即使它有点令人困惑。

    Is it safe to `delete this`?

    我认为额外的复制不是问题。可以肯定的是,您必须进行概要分析。没有分析信息,如果是我,我更喜欢第一种 b/c 的第二种方法,程序员更容易理解,但主要是意见。

    如果您想让对象更简单地操作指向自身的共享指针等,您可能还想查看 C++11 中的 shared_from_this 模板。

    【讨论】:

    • 谢谢你提醒我shared_from_this
    • 请看一下我编辑的问题,即使用shared_from_this的代码——这应该怎么用?
    • 当然,我想更简单的可能是if (some_condition) { return std::make_shared&lt;foo1&gt;(); } else { return shared_from_this(); }
    猜你喜欢
    • 1970-01-01
    • 2020-02-21
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 2013-08-23
    • 1970-01-01
    • 2020-09-18
    相关资源
    最近更新 更多