释放STL向量中的对象
Freeing an object in an STL vector
我有下面的例子来释放STL向量中的对象。
#include <map>
#include <string>
using namespace std;
class Test
{
public:
char* name;
int id;
Test(char* n, int i);
};
Test::Test(char* n, int i)
{
name = n;
id = i;
}
int main ()
{
Test* t = new Test("hi", 5);
vector<Test> v;
v.insert(v.end(), *t);
for(vector<Test>::iterator it = v.begin(); it != v.end(); it++)
{
if (it->id == 5)
{
Test* ptr = &*it;
v.erase(it);
delete ptr;
break;
}
}
return 0;
}
根据我一直在研究的情况,这应该是正确的方法。然而,valgrind给了我这样的抱怨:
==7404== Invalid free() / delete / delete[]
==7404== at 0x4A05130: operator delete(void*) (vg_replace_malloc.c:244)
==7404== by 0x400FD2: __gnu_cxx::new_allocator<Test>::deallocate(Test*, unsigned long) (new_allocator.h:94)
==7404== by 0x401004: std::_Vector_base<Test, std::allocator<Test> >::_M_deallocate(Test*, unsigned long) (stl_vector.h:133)
==7404== by 0x401045: std::_Vector_base<Test, std::allocator<Test> >::~_Vector_base() (stl_vector.h:119)
==7404== by 0x40109C: std::vector<Test, std::allocator<Test> >::~vector() (stl_vector.h:272)
==7404== by 0x400998: main (test.cc:46)
==7404== Address 0x4C58070 is 0 bytes inside a block of size 16 free'd
==7404== at 0x4A05130: operator delete(void*) (vg_replace_malloc.c:244)
==7404== by 0x40098A: main (test.cc:41)
还有内存泄漏。做这件事的正确方法是什么?
这是的老规则
每一个
new
都应有一个delete
在您的情况下,调用new
的唯一时间是分配Test
的实例(目前还不清楚为什么要这样做,但我们忽略它)。然后将该对象的副本插入vector
;您没有为插入的对象分配内存。因此,不需要在vector
管理的内存上调用delete
。
另一方面,您正在泄漏内存,因为您从未对分配的内存调用delete
。添加
delete t;
在您使用完t
后的某个地方的代码中
现在,如果您的向量被声明为vector<Test *>
,那么在从向量中删除元素之前,您需要手动delete
元素。但是,如果您需要一个指针向量,那么您应该始终使用vector<unique_ptr<Test>>
(或其他智能指针,或boost::ptr_vector
),在这种情况下,不需要手动调用delete
。
测试*t=新测试("hi",5);
您正在泄漏此对象。您将对象的副本存储到vector
中,但之后不会释放原始对象。
v.insert(v.end(),*t);
请改用v.push_back(*t)
。
if(it->id==5);
分号是错误的。你需要删除它。
测试*ptr=&它v.擦除(它);删除ptr;
erase()
可以,但delete
不行。您没有在vector
中存储用new
分配的对象,因此根本不应该尝试delete
。你试图释放你不拥有的记忆。
话虽如此,你有两个选择:
-
在
vector
:中存储指针int main () { Test* t = new Test("hi", 5); vector<Test*> v; v.push_back(t); for(vector<Test*>::iterator it = v.begin(); it != v.end(); ++it) { Test* ptr = *it; if (ptr->id == 5) { v.erase(it); delete ptr; break; } } return 0; }
-
不要在矢量中存储指针:
int main () { /* Test *t = new Test("hi", 5); vector<Test> v; v.push_back(*t); delete t; // don't forget this! */ vector<Test> v; v.push_back(Test("hi", 5)); for(vector<Test>::iterator it = v.begin(); it != v.end(); ++it) { if (it->id == 5) { v.erase(it); break; } } return 0; }
仅供参考,您可以考虑使用std::find_if()
而不是手动循环:
struct IsId
{
int _id;
IsId(int id) : _id(id) {}
bool operator()(const Test &src) const { return (src.id == _id); }
};
vector<Test>::iterator it = find_if(v.begin(), v.end(), IsId(5));
if (it != v.end())
{
v.erase(it);
}
vector::erase:
从矢量中删除单个元素(位置)或一系列元素([第一个,最后一个))。
这有效地减少了容器大小,减少了被销毁的元素数量。
所以你只需要使用擦除功能。你不需要使用指针和删除。
请注意,当您将新实例插入vector:时
v.insert(v.end(), *t);
该类在向量中再次被复制构造,因此您只剩下两个单独的实例,一个在t
中,一个位于v[0]
中。
用sane C++编写代码的正确方法如下:
int main()
{
std::vector<Test> v { Test(""hi", 5) };
} // returns 0, frees all allocated resources
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- 从多个源构造一个对象,包括一个对象向量
- 如何从文件中读取两个字符串和数字数组,并将它们存储在对象向量中
- 对象 C++ 向量的 STL 容器
- 初始化C++中的对象向量
- 从自定义类获取对象向量中的 max 元素
- 如何在 c++ 中打印存档中的对象向量
- 如何将包含另一个对象向量的对象保存到文件中,并使用C++中的二进制文件从文件中读回?
- 尝试重载输出运算符时,我无法遍历对象向量
- 如何在C++中打印对象向量的内容
- 打印出对象向量中的每个元素C++
- 在 c++ 的构造函数中分配对象向量时出错
- 遍历对象向量,并找到与从文本文件中提取的对象匹配的变量
- 对象向量是否在堆或堆栈上分配C++?
- 基于不同字段的对象向量的排序功能
- 有没有一种简单的方法可以在对象向量上调用构造函数?
- 用rapidjson读取子对象向量
- 尝试使用比较运算符对对象向量进行排序
- 如何用对象向量重载 cin(>>)
- 如何将某个元素从shared_ptr擦除到对象向量?