结论

  1. allocator 分配器是定义内存模型的类,用于标准库的某些部分,尤其是 STL 容器,如果所有标准容器的最后一个(可选)模板参数没有指定,那么它将使用这个分配器,并且它是标准库中唯一一个预定义的分配器
  2. vector 中存放的如果是对象类型,则会通过 allocator 在堆上开辟足够的空间来存放和管理集合中的对象
  3. 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
空指针