从模板化队列中检索时的核心转储

Core Dump When Retrieving From Templated Queue

背景

我想要一个 class MyClass 来存储不同类型的队列。为此,我创建了一个接口 ValueInterface 和一个派生 class Value<T>。我现在可以使用 queue<ValueInterface> 成员变量将此派生 class 的实例存储在 MyClass 中。

注意: 为了我自己的目的,我有意保持 MyClass 非模板化,我想要依赖模板函数。

目标

我有下面的代码可以编译,但是下面的测试代码中的 运行 导致核心转储。我认为我在使用 std::unique_ptr 时很小心,并确保尽可能使用 std::moveGetValueAndAdvance<T> 函数导致错误。当我尝试从模板化队列中检索时出了点问题。我知道它很乱,我假设 static_cast 可以工作,但是 我怎样才能从存储 std::queuestd::queue 中检索 Value<T> 14=] ?

我不知道问题是否出在 StoreValueGetValueAndAdvance 上,或者整个设计是否存在缺陷并且在类型敏感语言中是不可能的。

测试中的用法: 这是我想要完成的功能。这是假设每个 MyClass 一次只用于一种类型。因此,让我们假设没有人会在同一个 MyClass 对象上调用 StoreValue<int>(4)StoreValue<string>("hello")。但出于我自己的原因,我想保持 MyClass 非模板化。

 MyClass my_class;
 my_class.StoreValue<int>(5);
 int val;
 my_class.GetValueAndAdvance<int>(&val);
 std::cout << "value: " << val; // Should print "value: 5"

代码:

class ValueInterface {};

template <class T>
class Value : public ValueInterface {
 public:
  Value(T val) : value_(val){};
  T get() { return value_; }

 private:
  const T& value_;
};

class MyClass {
 public:
  template <class T>
  void GetValueAndAdvance(T* out_val) {
    if (!queued_values_.empty()) {
      auto unique_value = std::move(queued_values_.front());
      queued_values_.pop();
      auto unique_value_typed = static_cast<Value<T>*>(unique_value.get());
      *out_val = unique_value_typed->get();
      // Prints 0 even though it should return 5 based on the test code (below)
      std::cout << "value: " << unique_value_typed->get(); 
    }
    return;
  }

  template <class T>
  MyClass* StoreValue(const T& value) {
    auto wrapped_value = std::make_unique<Value<T>>(value);
    queued_values_.push(std::move(wrapped_value));
    return this;
  }

 private:
  std::queue<std::unique_ptr<ValueInterface>> queued_values_;
};

错误消息片段

F0418 18:08:57.928949  244111 debugallocation.cc:763] RAW: delete size mismatch: passed size 1 != true size 4
    @     0x7fda024f8a1f  (anonymous namespace)::RawLogVA()
    @     0x7fda024f8525  base_raw_logging::RawLog()
    @           0x42b162  tc_delete_sized
    @           0x40c595  std::default_delete<>::operator()()
    @           0x40c503  std::unique_ptr<>::~unique_ptr()
    @           0x40b552  mynamespace::MyClass::GetValueAndAdvance<>()

问题出在 Value class 中,其中 value_ 被定义为 对常量值 的引用

const T& value_;

value_ 定义为正常(非参考)值

const T value_;

你应该从 std::cout.

得到 5

观察Value<T>

的构造函数
Value(T val) : value_(val){};

value_ 引用被初始化为一个 临时 变量 (val),该变量在构造函数结束时超出范围.

因此 value_ 绑定到可以重复使用的内存,因此具有未定义的值。