c++ - 在类型删除的小对象优化中调试崩溃

标签 c++ virtual-functions type-erasure

我正在实现一个对小对象执行类型删除的类,但遇到了一个我不理解的段错误。

以下程序:

#include <iostream>
#include <type_traits>

struct small_object
{
  public:
    template<class T>
    small_object(const T& value)
    {
      new(&storage_) concrete<T>(value);
    }

    ~small_object()
    {
      get_abstract().~abstract();
    }

    void print() const
    {
      // XXX crash here
      get_abstract().print();
    }

  private:
    struct abstract
    {
      virtual ~abstract(){}

      virtual void print() const = 0;
    };

    template<class T>
    struct concrete
    {
      concrete(const T& value) : value_(value) {}

      void print() const
      {
        std::cout << value_ << std::endl;
      }

      T value_;
    };

    abstract& get_abstract()
    {
      return *reinterpret_cast<abstract*>(&storage_);
    }

    const abstract& get_abstract() const
    {
      return *reinterpret_cast<const abstract*>(&storage_);
    }

    typename std::aligned_storage<4 * sizeof(void*)> storage_;
};

int main()
{
  small_object object(13);

  // XXX i expect this line to print '13' to the terminal but it crashes
  object.print();

  return 0;
}

XXX 指示的行处崩溃。

我认为问题是对 .print() 的虚拟调用没有被正确地动态调度,但我不明白为什么。

谁能告诉我我错过了什么?

最佳答案

您没有导出 concrete<T>来自 abstract ,因此当您使用放置 new 构造对象时,不会创建 vtable .因此,当您尝试调用虚函数时,它会失败; concrete<T>abstract在这个例子中实际上是完全不相关的类型。

我建议使用 override如果您使用的是 C++11 或更新版本,则使用关键字允许编译器在这种情况下生成错误。

关于c++ - 在类型删除的小对象优化中调试崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41514255/

相关文章:

c++ - 填充 vector 时的效率

c++ - CRTP 和基类定义的类型的可见性

c++ - 在不指向对象的情况下调用虚方法?

java - 为什么不能将 @SafeVarags 应用于最终类中的实例方法?

java - DataNucleus 可以持久保存使用泛型参数化的抽象基类吗?

c++ - 仅在当前目录中搜索标签

c++ - apple cpp 破坏宏参数粘贴

c++ - 从具有虚函数的基类继承的类上的 sizeof

c++ - 虚函数与回调

java - 违反检查通用对象列表的方法