繁体   English   中英

push_back到静态向量后的C ++释放

[英]C++ Deallocation after push_back to static vector

在下面的代码中,我尝试实现一个缓存的单例模式(每个Multiplication(n)仅应存在一次)。

  vector<Multiplication>& Multiplication::cacheVector() {
    static vector<Multiplication> cache({Multiplication(0)});

    return cache;
  }

  const Multiplication& Multiplication::getInstance(unsigned int order) {

    while (order >= cacheVector().size()) {
      cacheVector().push_back(Multiplication(cacheVector().size()));      
    }

    return cacheVector()[order];      
  }

问题是:当我尝试使用缓存的乘法实例时,出现了段错误。 Valgrind告诉我,我调用了无效读取,因为在getInstance函数中释放了数据:

==5471==    by 0x4C2054D: std::_Vector_base<tnp::Multiplication, std::allocator<tnp::Multiplication> >::_M_deallocate(tnp::Multiplication*, unsigned long) (stl_vector.h:174)
==5471==    by 0x4C2029D: _ZNSt6vectorIN3tnp14MultiplicationESaIS1_EE19_M_emplace_back_auxIJS1_EEEvDpOT_ (stl_vector.h:430)
==5471==    by 0x4C1FFDF: _ZNSt6vectorIN3tnp14MultiplicationESaIS1_EE12emplace_backIJS1_EEEvDpOT_ (vector.tcc:101)
==5471==    by 0x4C1EE9F: std::vector<tnp::Multiplication, std::allocator<tnp::Multiplication> >::push_back(tnp::Multiplication&&) (stl_vector.h:920)
==5471==    by 0x4C1DF52: tnp::Multiplication::getInstance(unsigned int) (multiplication.cpp:83)

乘法没有自己的副本构造函数和以下字段:

  class Multiplication { 

    const unsigned int order;
    const vector<Product> valueSum;
    const vector<Product> partialDerSum;
    const vector<Multiplication>& instances;

(除order == 0以外,实例是对缓存向量的向后引用),valueSum和partialDerSum向量可能发生解除分配。

那么,为什么C ++会对我的新乘法实例进行重新分配? 它不应该将其复制到向量中吗? 我想避免任何显式的堆分配,因为指针间接将对以后的性能造成一定的影响。

您尚未指出导致段错误的确切行,所以只是我的疯狂猜测:

可能您在某个地方存储了对Multiplication实例的引用,然后在vector中添加了新项,从而导致对其内部存储器进行vector重新分配,因此您的引用指向了释放的内存

不是崩溃的真正答案,而是对以下问题的解释:

那么,为什么C ++会对我的新乘法实例进行重新分配? 它不应该将其复制到向量中吗?

实际上,它确实可以复制或移动。

让我们来描述一下这一行:

cacheVector().push_back(Multiplication(cacheVector().size()));  

Multiplication(cacheVector().size())的地方分配的,但你的记忆cacheVector您是不是在同一个地方,所以载体复制或移动(这里肯定会移动)数据Multiplication ,同时创造cacheVector的实例。

这是一个小示例 ,可以帮助您理解这一点。

您会看到有一个对“普通”构造函数的调用,然后是对move构造函数的调用。 然后,编译必须删除已移至向量的实例,因此它确实会对使用“常规”构造函数分配的实例调用析构函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM