如何正确分配和取消分配矢量映射



我试图将数据保存在无序的向量映射中,使用uint32_t地址作为键。矢量需要存储在堆中,因此即使函数超出范围,我仍然可以访问数据。我这样分配:

using vectorBuffer = std::vector<uint8_t>;
using I2cVectorMap = std::unordered_map<address_t, vectorBuffer>;
using I2cVectorEntry = std::pair<address_t, vectorBuffer>;
if(auto i2cIter = i2cVectorMap.find(address); i2cIter == i2cVectorMap.end()) {
vectorBuffer * receiveVector = new vectorBuffer(maxReplyLen);
i2cVectorMap.insert(I2cVectorEntry(address, *receiveVector));
}
else {
// Already in map. readjust size
vectorBuffer * existingVector = &i2cIter->second;
existingVector->resize(maxReplyLen);
existingVector->shrink_to_fit();
}

像这样的解除分配(根据各种来源的建议,用空向量交换向量(:

// getting the address from another object.
address_t deviceAddress = i2cCookie->getAddress();
if(auto i2cIter = i2cVectorMap.find(deviceAddress); i2cIter != i2cVectorMap.end()) {
vectorBuffer().swap(i2cIter->second);
}

这是一个正确的实现吗?我将把映射条目的地址传递给启动I2C传输的驱动程序函数或处理数据的另一个对象。我想确保我没有内存泄漏。

提前感谢!

不,您不应该使用new。首先,需要直接new的情况很少见。

您不需要手动创建任何具有动态存储持续时间("在堆上"(的对象。标准库容器直接存储对象,而不是对象的引用或指针。他们将为这些对象进行分配并自行构建。您只向容器成员函数提供构造函数参数,容器(复制/移动(从这些函数构造存储的元素。

您可以将对象声明为自动变量(即"在堆栈上"(:

vectorBuffer receiveVector(maxReplyLen);
i2cVectorMap.insert(I2cVectorEntry(address, receiveVector));

或者对中间向量实例使用临时变量而不是命名变量(这也将使用移动操作而不是复制操作,因此性能更好(:

i2cVectorMap.insert(I2cVectorEntry(address, vectorBuffer(maxReplyLen)));

如果使用emplace而不是insert,也可以删除冗余对类型:

i2cVectorMap.emplace(address, vectorBuffer(maxReplyLen));

您不需要指针来调用映射中对象的方法:

vectorBuffer& existingVector = i2cIter->second;
existingVector.resize(maxReplyLen);
existingVector.shrink_to_fit();

要从映射中删除元素,请使用其.erase成员函数:

i2cVectorMap.erase(deviceAddress);

你不需要做任何其他事情。这将破坏并释放向量。

当你不再需要映射及其包含的向量时,你也不需要做任何事情。当定义映射的范围剩下时,映射的析构函数将自动清理所有内容。

最新更新