使用enable_shared_from_this时出现bad_weak_ptr

问题描述 投票:0回答:2

我有一个基础班

class eventreceiver {
public:
  eventreceiver() = default;
  virtual ~eventreceiver() = default;

  virtual void on_quit();
}

我有一个使用它的课程

class engine : public eventreceiver, std::enable_shared_from_this<engine> {
public:
  virtual ~engine() = default;

  [[nodiscard]] static std::shared_ptr<engine> create();

  void init(std::string_view title, int32_t width, int32_t height, bool fullscreen = false);

  void add_loopable(std::shared_ptr<loopable> loopable);

  void run();

protected:
  virtual void on_quit() override;

private:
  engine() = default;

  bool _running;

  std::list<std::shared_ptr<loopable>> _loopables;
  std::shared_ptr<window> _window;
  std::shared_ptr<renderer> _renderer;
  std::shared_ptr<eventmanager> _eventmanager;
};

当我尝试从下面

shared_from_this
传递shared_ptr时

void engine::init(std::string_view title, int32_t width, int32_t height, bool fullscreen) {
  _running = true;
  _window = std::make_shared<window>(title, width, height, fullscreen);
  _renderer = _window->create_renderer();
  _eventmanager = std::make_shared<eventmanager>();

  _eventmanager->add_receiver(std::dynamic_pointer_cast<eventreceiver>(shared_from_this())); // HERE

  add_loopable(std::make_shared<framerate>());
}

我收到异常情况

bad_weak_ptr

我做错了什么以及如何将“engine”的shared_ptr传递给“_eventmanager”?

编辑:最小可重现示例 -> https://onlinegdb.com/4VTq1mMnc

c++ c++17 std
2个回答
0
投票
如果

shared_from_this()

this
管理,shared_ptr
 
只能
被调用。

这行不通:

engine e;
e.init();

这会起作用:

auto e = engine::create();
e->init();

在不相关的注释中,您应该避免

dynamic_cast
,它是智能指针对应部分
std::dynamic_pointer_cast
。特别是,这里不需要转换:
std::shared_ptr<Derived>
可以隐式转换为
std::shared_ptr<Base>
(就像
Derived*
可以隐式转换为
Base*
一样)。


0
投票

您不能共享指向堆栈上创建的内容的指针! 您以无效的方式构造了

engine
。从
std::enable_shared_from_this
继承的任何内容都应该分配在堆上。

最好的方法是 std:make_shared:

int main()
{
    auto e = std::make_shared<engine>();
    e->init();

    return 0;
}

https://godbolt.org/z/s1a6MWEdK

另请注意,您忘记了

public
之前的
std::enable_shared_from_this<engine>
关键字!

© www.soinside.com 2019 - 2024. All rights reserved.