结论
- allocator 分配器是定义内存模型的类,用于标准库的某些部分,尤其是 STL 容器,如果所有标准容器的最后一个(可选)模板参数没有指定,那么它将使用这个分配器,并且它是标准库中唯一一个预定义的分配器
- vector 中存放的如果是对象类型,则会通过 allocator 在堆上开辟足够的空间来存放和管理集合中的对象
- vector 中存放指针类型,一定要记得手动释放内存
存放对象
class Person{
public:
Person(int age, int id){
m_age = age;
m_id = id;
cout << "Person(int, int)..." << endl;
}
Person(const Person& p){
m_age = p.m_age;
m_id = p.m_id;
cout << "Person(const Person& p)..." << endl;
}
~Person(){
cout << "~Person()..." << endl;
}
void* operator new(size_t size){
void* p = malloc(size);
cout << "new()..." << endl;
return p;
}
void operator delete(void *p){
cout << "delete()..." << endl;
if(p != NULL){
free(p);
p = NULL;
}
}
void show(){
cout << "Age: " << m_age << " Id: " << m_id << endl;
}
private:
int m_age;
int m_id;
};
void printPerson(Person &p){
p.show();
}
int main()
{
// vector 中存放对象类型
std::vector<Person> v;
v.reserve(3);
v.push_back(Person(10, 20));
v.push_back(Person(30, 40));
v.push_back(Person(50, 60));
// 遍历 vector
for(vector<Person>::iterator it = v.begin(); it != v.end(); it++){
// 迭代器是指针
it->show();
// 也可以这么写
// (*it).show();
}
for_each(v.begin(), v.end(), printPerson); // 回调函数不支持函数重载??
// 测试删除
Person* pp = &v[0]; // 记录 vector 中第一个元素的地址
// 方式一
v.clear(); // 这种释放方式,pp 指针仍然可以访问已释放的地址,存在安全隐患
// 方式二
vector<Person>().swap(v); // 这种方式不仅可以释放内存,还可以防止其它指针对已经释放的内存进行非法访问
// 利用 swap 函数和临时对象交换内存,交换以后,临时对象消失
cout << v.size() << endl;
if(pp != NULL){
pp->show();
}else{
cout << "空指针" << endl;
}
return 0;
}
方式一输出:
Person(int, int)...
Person(const Person& p)...
~Person()...
Person(int, int)...
Person(const Person& p)...
~Person()...
Person(int, int)...
Person(const Person& p)...
~Person()...
Age: 10 Id: 20
Age: 30 Id: 40
Age: 50 Id: 60
Age: 10 Id: 20
Age: 30 Id: 40
Age: 50 Id: 60
~Person()...
~Person()...
~Person()...
0
Age: 10 Id: 20
方式二输出:
Person(int, int)...
Person(const Person& p)...
~Person()...
Person(int, int)...
Person(const Person& p)...
~Person()...
Person(int, int)...
Person(const Person& p)...
~Person()...
Age: 10 Id: 20
Age: 30 Id: 40
Age: 50 Id: 60
Age: 10 Id: 20
Age: 30 Id: 40
Age: 50 Id: 60
~Person()...
~Person()...
~Person()...
0
Age: 0 Id: 0
存放指针
void printPerson(Person *&p){
if(p == NULL){
cout << "指针为空" << endl;
return;
}
p->show();
}
void delPerson(Person *&p){
delete p;
p = NULL;
}
int main()
{
// vector 中存放对象指针,就必须手动释放内存
vector<Person*> v;
v.reserve(3);
v.push_back(new Person(10, 20));
v.push_back(new Person(30, 40));
v.push_back(new Person(50, 60));
for_each(v.begin(), v.end(), printPerson); // 不支持函数重载??
// 手动释放内存
// for_each(v.begin(), v.end(), delPerson);
// for_each(v.begin(), v.end(), printPerson);
// 删除测试
Person *pp = v[0]; // 记录 vector 中第一个元素的地址,实际上是拷贝了指向第一个 Person 对象的地址
// 除非手动 delete 掉 vector 中的指针,否则不管是 clear 还是 swap 都没有真正释放内存
// 这两种方式只是把 vector 对象释放了,存储的指针所指向的空间并没有释放
// 方式一
v.clear(); // 这种情况下,pp 指针仍然可以访问
// 方式二
vector<Person*>().swap(v);
cout << v.size() << endl;
if(pp != NULL){
pp->show();
}else{
cout << "空指针" << endl;
}
return 0;
}
方式一输出:
new()...
Person(int, int)...
new()...
Person(int, int)...
new()...
Person(int, int)...
Age: 10 Id: 20
Age: 30 Id: 40
Age: 50 Id: 60
0
Age: 10 Id: 20
方式二输出:
new()...
Person(int, int)...
new()...
Person(int, int)...
new()...
Person(int, int)...
Age: 10 Id: 20
Age: 30 Id: 40
Age: 50 Id: 60
0
Age: 10 Id: 20
手动释放内存输出:
new()...
Person(int, int)...
new()...
Person(int, int)...
new()...
Person(int, int)...
Age: 10 Id: 20
Age: 30 Id: 40
Age: 50 Id: 60
~Person()...
delete()...
~Person()...
delete()...
~Person()...
delete()...
指针为空
指针为空
指针为空
0
空指针