首先,我的动机是在C计算内核等C之上进行有效的内存管理。我尝试使用std::unique_ptr
和std::vector
,我的代码看起来像
// my data container
typedef std::unique_ptr<double> my_type;
std::vector<my_type> my_storage;
// when I need some memory for computation kernel
my_storage.push_back(my_type());
my_storage.back.reset(new double[some_length]);
// get pointer to do computational stuff
double *p_data=my_storage.back.get();
在实践中注意 p_data
可以存储在其他容器中(例如地图),以根据域问题索引每个分配的数组,但是,我的主要问题是
这是
std::vector
一个不错的选择吗?还有其他容器,例如std::list
/set
?我的分配方法是否有基本问题?
假设我使用
p_data
用于某些操作,现在我想释放由RAW指针p_data
释放的内存块,这里的最佳实践是什么?
首先,如果要分配一个数组,则需要使用专业 std::unique_ptr<T[]>
,否则您将在内存版本中获得delete []
,而是简单的delete
。
std::vector
是一个不错的选择,除非您有任何明确的理由使用不同的东西。例如,如果您要在容器中移动许多元素,则std::list
可以表现更好(更少的memmove
操作可以改变一切)。
关于如何管理内存,它主要取决于利用率的模式。如果my_storage
主要负责所有内容(在您的规范中,因为unique_ptr
表示所有权),则意味着它将是唯一可以发布内存的人。可以简单地致电my_storage[i].reset()
。
注意到,在其他集合中存储原始的对象的原始指针会导致悬挂的指针,例如:
:using my_type = std::unique_ptr<double[]>;
using my_storage = std::vector<my_type>;
my_storage data;
data.push_back(my_type(new double[100]));
std::vector<double*> rawData;
rawData.push_back(data[0].get());
data.clear(); // delete [] is called on array and memory is released
*rawData[0] = 1.2; // accessing a dangling pointer -> bad
这可能是一个问题,如果data
最后释放,那么没有问题,否则您可以将const引用存储到std::unique_ptr
上,以便至少您能够检查内存是否仍然有效,例如:
using my_type = std::unique_ptr<double[]>;
using my_managed_type = std::reference_wrapper<const my_type>;
std::vector<my_managed_type> rawData;
在包括std::vector
在内的任何STL容器中使用std::unique_ptr
通常都很好。但是,您没有以正确的方式使用std::unique_ptr
(您没有使用IT的数组专业版),也不需要完全使用back.reset()
。改用此方法:
// my data container
typedef std::unique_ptr<double[]> my_type;
// or: using my_type = std::unique_ptr<double[]>;
std::vector<my_type> my_storage;
my_type ptr(new double[some_length]);
my_storage.push_back(std::move(ptr));
// or: my_storage.push_back(my_type(new double[some_length]));
// or: my_storage.emplace_back(new double[some_length]);