在下面的代码中,我尝试实现一个缓存的单例模式(每个乘法(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];
}问题是:当我尝试使用缓存的乘法实例时,我会得到一个分段错误。瓦兰德告诉我,我调用无效的读取,因为数据在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++要对我的新乘法实例进行重新分配呢?它不应该把它复制到向量中吗?我想避免任何显式的堆分配,因为指针间接会在以后的路上造成一些性能上的损失。
发布于 2013-11-27 12:31:04
你还没有指出导致分段故障的确切线路,所以我只是粗略地猜测:
您可能在某个地方存储了对乘法实例的引用,然后在向量中添加了新项,从而导致向向量重新分配它的内部内存,因此您的引用点指向了已分配的内存
发布于 2013-11-27 12:36:01
对于它崩溃的原因,不是一个真正的答案,而是对这些问题的解释:
那么,为什么C++要对我的新乘法实例进行重新分配呢?它不应该把它复制到向量中吗?
事实上,它确实复制或移动。
让我们稍微描述一下这一行:
cacheVector().push_back(Multiplication(cacheVector().size())); Multiplication(cacheVector().size())被分配到某个地方,但是cacheVector的内存不在同一个位置,因此向量复制或移动(这里肯定是移动)从Multiplication中创建cacheVector实例时的数据。
可以帮助您理解这一点的下面是一个小例子。
您可以看到对“普通”构造函数的调用,然后是对move构造函数的调用。然后,编译必须删除移动到向量的实例,因此它确实调用了与"normal“构造函数一起分配的实例上的析构函数。
https://stackoverflow.com/questions/20242359
复制相似问题