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

时间:2017-04-18 23:21:28

标签: c++ templates c++14 unique-ptr coredump

背景

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

注意 出于我自己的目的,我故意试图保持MyClass非模板,我想要依靠模板化的功能。

目标

我有下面的代码编译,但在下面的测试代码中运行会导致核心转储。我认为在使用std::unique_ptr时我非常小心,并确保在可能的情况下使用std::moveGetValueAndAdvance<T>函数会导致错误。当我尝试从模板化队列中检索时出错了。我知道它很乱,我假设static_cast会起作用,但是我怎样才能从Value<T>中检索std::queue,哪个存储ValueInterface

我不知道问题是在StoreValue还是GetValueAndAdvance,还是整个设计存在缺陷,而且在类型敏感的语言中是不可能的。

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

1 个答案:

答案 0 :(得分:1)

问题出在Value类,其中value_被定义为引用到常量值

const T& value_;

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

const T value_;

您应该从5获得std::cout

观察Value<T>

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

value_引用初始化为(绑定到)临时变量(val),该变量超出了构造函数末尾的范围。

所以value_被限制在一个可以重用的内存中,因此具有未定义的值。