使用unique_ptr和适当的容器进行内存管理

Use unique_ptr and appropriate container to do memory management

本文关键字:管理 内存 unique ptr 使用      更新时间:2023-10-16

首先,我的动机是在C计算内核等C之上进行有效的内存管理。我尝试使用std::unique_ptrstd::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 可以存储在其他容器中(例如地图),以根据域问题索引每个分配的数组,但是,我的主要问题是

  1. 这是std::vector一个不错的选择吗?还有其他容器,例如std::list/set

  2. 我的分配方法是否有基本问题?

  3. 假设我使用 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]);