C++ std::分配器在重新分配后不保留旧的已分配项
我试图实现一个向量类,该类分配一块内存,如果需要包含更多项,则最终重新分配它。C++ std::分配器在重新分配后不保留旧的已分配项,c++,allocator,C++,Allocator,我试图实现一个向量类,该类分配一块内存,如果需要包含更多项,则最终重新分配它。 我正在使用std::allocator执行以下操作: #include <iostream> #include <stdexcept> using namespace std; template <class T> class Vector { private: T* data; allocator<T> data_all; int leng
我正在使用std::allocator执行以下操作:
#include <iostream>
#include <stdexcept>
using namespace std;
template <class T>
class Vector
{
private:
T* data;
allocator<T> data_all;
int length;
int _size;
static const int block_size=10;
void init()
{
length=0;
_size=block_size;
data=data_all.allocate(block_size,NULL);
}
public:
Vector()
{
init();
}
int size() const
{
return length;
}
void push_back(T item)
{
length++;
if(length > _size)
{
_size+=block_size;
data=data_all.allocate(_size,data);
}
data_all.construct(&data[length-1],item);
}
T& operator[] (int i)
{
if(i<0 || i>= length)
throw out_of_range("The index is out of vector range");
return data[i];
}
};
int main(int argc, char** argv)
{
Vector<int> v;
for(int i=0; i<20; i++)
v.push_back(i);
for(int i=0; i<v.size(); i++)
cout << v[i] << "\t";
return 0;
}
而不是:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
为什么会有这种行为?C++中没有一种方法可以重新分配与C一样的连续项目吗?p> allocate的第二个参数只是一个提示,分配器可以使用它来尝试返回接近旧内存的新内存,但是被
std::allocator
忽略,对于向量类容器来说非常无用,因为所有元素都彼此接近,因为它们在一个连续的块中
您似乎希望它复制现有数据。不会的。你必须这样做,从旧的内存块复制到新的内存块
你也在泄露旧的记忆。你需要取消分配它
你想要的是:
void push_back(const T& item)
{
if (length == _size)
{
T* new_data = data_all.allocate(_size+block_size);
// N.B. if any of the following copies throws new_data will be leaked
std::uninitialized_copy(data, data+length, new_data);
std::destroy(data, data+length);
data_all.deallocate(data, _size);
data = new_data;
_size+=block_size;
}
data_all.construct(&data[length++],item);
}
难道没有其他方法,至少尝试在一个连续的位置(如C中的ReLoLc)分配新的块吗?简短的回答是:不,长回答:<代码> ReLoC/
std::allocator::allocate
返回未初始化的内存,我认为您希望在push_back
示例中使用而不是std::copy
。为了提高性能,我想使用malloc和realloc,分配指针,并且每个指针都将用新指针初始化。
void push_back(const T& item)
{
if (length == _size)
{
T* new_data = data_all.allocate(_size+block_size);
// N.B. if any of the following copies throws new_data will be leaked
std::uninitialized_copy(data, data+length, new_data);
std::destroy(data, data+length);
data_all.deallocate(data, _size);
data = new_data;
_size+=block_size;
}
data_all.construct(&data[length++],item);
}