我对在C ++中删除东西感到困惑
如果我声明一个对象数组,并且我使用clear()
函数。我可以确定内存已被释放吗?
例如:
tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;
tempVector.pushback(obj1);
tempVector.pushback(obj2);
我可以安全地拨打清除以释放所有内存吗?或者我是否需要逐个删除才能逐个删除?
tempVector.clear();
如果将此场景更改为对象指针,答案是否与上述相同?
vector<tempObject> *tempVector;
//push objects....
tempVector->clear();
答案 0 :(得分:77)
你可以调用clear,这会破坏所有对象,但这不会释放内存。循环使用各个元素也无济于事(你甚至建议对这些对象采取什么行动?)你可以做的是:
vector<tempObject>().swap(tempVector);
这将创建一个没有分配内存的空向量,并将其与tempVector交换,从而有效地释放内存。
C ++ 11也有函数shrink_to_fit
,你可以在调用clear()之后调用它,理论上它会缩小容量以适应大小(现在为0)。但是,这是一个非约束性请求,您的实现可以忽略它。
答案 1 :(得分:21)
这里有两个不同的东西:
例如:
{
vector<MyObject> v;
// do some stuff, push some objects onto v
v.clear(); // 1
// maybe do some more stuff
} // 2
在1
,您清除v
:这会破坏它存储的所有对象。每个人都会得到它的析构函数,如果你写了一个,那么MyObject
拥有的任何东西现在都被释放了。
但是,向量v
有权保留原始存储空间以备日后使用。
如果您决定在1
和2
之间推送更多内容,则可以节省时间,因为它可以重复使用旧内存。
在2
,向量v
超出范围:自1
以来你推入它的任何对象都将被销毁(就好像你明确地再次调用了clear),但是现在底层存储也已发布(v
将无法重新使用它。)
如果我更改示例以使v
成为指针,则需要显式删除它,因为超出2
范围的指针不会为您执行此操作。在这种情况下,最好使用类似std::unique_ptr
的内容,但如果不这样做,v
被泄露,它分配的存储也将被泄露。如上所述,您需要确保删除v
,并且调用clear
是不够的。
答案 2 :(得分:14)
vector::clear()
不释放向量分配的内存来存储对象;它为它所拥有的对象调用析构函数。
例如,如果向量使用数组作为后备存储并且当前包含10个元素,则调用clear()
将调用数组中每个对象的析构函数,但后备数组将不会deallocated ,因此仍然有sizeof(T) * 10
个字节分配给向量(至少)。 size()
将为0,但size()
返回向量中的元素数,不一定是后备存储的大小。
至于您的第二个问题,您使用new
分配的任何内容都必须与delete
取消分配。出于这个原因,通常不会维护指向向量的指针。很少(如果有的话)有充分的理由这样做,你可以防止矢量在离开范围时被清理干净。但是,无论分配方式如何,调用clear()
仍将采取相同的行动。
答案 3 :(得分:2)
移动语义提供了一种直接释放内存的方法,只需简单地从空值中应用assignment (=) operator:
std::vector<uint32_t> vec(100, 0);
std::cout << vec.capacity(); // 100
vec = vector<uint32_t>(); // Same as "vector<uint32_t>().swap(vec)";
std::cout << vec.capacity(); // 0
它与其他答案中所述的基于“ swap()”的方法一样有效(实际上,两者在概念上都在做同一件事)。但是,在可读性方面,赋值版本可以更好地表达程序员的意图,同时更加简洁。
答案 4 :(得分:1)
如果我使用
clear()
成员函数。我可以确定内存已释放吗?
否,clear()
成员函数会破坏向量中包含的每个对象,但它会使向量的capacity保持不变。它会影响向量的大小,但不会影响容量。
如果要更改向量的容量,可以使用clear-and-minimize idiom,即创建一个(临时)空向量,然后交换两个向量。
您可以轻松了解每种方法如何影响容量。考虑下面的函数模板,该模板在传递的向量上调用clear()
成员函数:
template<typename T>
auto clear(std::vector<T>& vec) {
vec.clear();
return vec.capacity();
}
现在,考虑将传递的矢量交换为空的函数模板empty_swap()
:
template<typename T>
auto empty_swap(std::vector<T>& vec) {
std::vector<T>().swap(vec);
return vec.capacity();
}
两个函数模板都在返回时返回向量的容量,然后:
std::vector<double> v(1000), u(1000);
std::cout << clear(v) << '\n';
std::cout << empty_swap(u) << '\n';
输出:
1000
0
答案 5 :(得分:0)
如果你需要反复使用向量,并且当前代码在循环或每个函数调用中重复声明它,很可能会耗尽内存。我建议你在外面声明它,将它们作为指针传递给你的函数并使用:
my_arr.resize()
这样,您可以继续为向量使用相同的内存序列,而不是每次都请求新的序列。 希望这有帮助。 注意:将其调整为不同大小可能会添加随机值。如果需要,传递一个整数(如0)以初始化它们。
答案 6 :(得分:0)
您可以通过以下方式释放vector使用的内存:
public subscribe = (data: IQueue) => {
if (Queues.queues[data.name]) {
const handler = Queues.queues[data.name].hasOwnProperty('handler');
}
Queues.queues[data.name] = data;
};
public unsubscribe = (queue, handler) => {
const result = Queues.queues[queue];
};