[英]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.