首页 > 解决方案 > 将 shared_ptr 用于不透明类型时的非虚拟析构函数

问题描述

在下面的代码中,Base是一个带有非虚拟析构函数的抽象基类。

Derived,一个具体类型,只能在make_thing()工厂函数内部实例化(它的声明和定义仅在 的范围内可见make_thing())。

我的理解是,由于std::shared_ptr<T>在构造点存储了具体删除器,因此Derived通过std::shared_ptr<Base>.

如果make_thing()返回 astd::unique_ptr<Base>则不会编译,如果返回 则将是未定义的行为Base*

虽然代码按预期工作,但我想知道它是否包含未定义的行为。

#include <iostream>
#include <memory>

class Base {
 public:
  void method() const noexcept { return this->do_method(); }

 protected:
  ~Base() noexcept { std::cout << "~Base()\n"; }

 private:
  virtual void do_method() const noexcept = 0;
};

std::shared_ptr<Base> make_thing() {
  class Derived final : public Base {
   public:
    ~Derived() noexcept { std::cout << "~Derived()\n"; }

   private:
    void do_method() const noexcept override {
      std::cout << "Derived::do_method()\n";
    }
  };

  return std::make_shared<Derived>();
};

int main() {
  // only way to instantiate Derived
  auto thing = make_thing();
  thing->method();
}

样品运行:

$ clang++ example.cpp -std=c++20
$ ./a.out
Derived::do_method()
~Derived()
~Base()

标签: c++shared-ptrundefined-behavior

解决方案


推荐阅读