您的位置:首页 > 其它

vector构建和销毁需要注意的两个问题

2010-03-31 17:54 549 查看
【关于vector的构建】向vector容器添加对象,vector会在指定的位置保存一个该对象的副本,因此拷贝构造函数会被调用。下面是对push_back()函数的官方解释:
// Adds a new element at the end of the vector, after its current last element.
// The content of this new element is initialized to a copy of x.
void push_back(const T& x);
下面是vc++6.0下面的一个示例代码:
#include <iostream>;
#include <vector>;
using namespace std;

class Test
{
public:
    Test()
    {
        n = 0;
        cout << "default constructor is called!" << endl;
    }

    explicit Test(int m)
    {
        n = m;
    }

    Test(const Test& other)
    {
        count++; // 对拷贝构造函数调用进行计数
        n = other.n;
        cout << "copy constructor is called" << count << "th" << endl;
    }

    ~Test()
    {
        cout << "destructor is called!" << endl;
    }

public:
    static int count;

    int n;
};

int Test::count = 0;

int main()
{
    Test b(10);
    vector<test> vect(10); // 初始化vect空间大小为10
    
    Test::count = 0;       // 重置i的值为零,对拷贝构造函数调用次数重新计数
    vect.push_back(b);

    return 0;
}

// 这段代码的输出(VC++6.0):
default constructor is called!
copy constructor is called 1th
copy constructor is called 2th
copy constructor is called 3th
copy constructor is called 4th
copy constructor is called 5th
copy constructor is called 6th
copy constructor is called 7th
copy constructor is called 8th
copy constructor is called 9th
copy constructor is called 10th
destructor is called!
copy constructor is called 1th
copy constructor is called 2th
copy constructor is called 3th
copy constructor is called 4th
copy constructor is called 5th
copy constructor is called 6th
copy constructor is called 7th
copy constructor is called 8th
copy constructor is called 9th
copy constructor is called 10th
copy constructor is called 11th
destructor is called!
destructor is called!
destructor is called!
destructor is called!
destructor is called!
destructor is called!
destructor is called!
destructor is called!
destructor is called!
destructor is called!
对于以上输出内容的解释:
1. 创建一个临时对象,会调用默认构造函数;

2. 然后,使用该临时对象初始化vect中的10元素,从而出现了10次拷贝构造函数调用;

3. 初始化完毕后,释放该临时对象,调用析构函数;

4. 向vect尾部添加元素b,vect需要重新分配空间大小容纳新的元素,开辟11个Test对象空间并进行初始化,产生11次拷贝构造函数的调用;

5. main()函数结束,vect生命周期结束,释放所有元素,产生11次析构函数调用。

通过以上例子,我们发现vector直接保存对象的额外开销非常之大,主要是拷贝构造函数的调用,而一个较为好的解决方式是保存对象的指针或share_ptr。

【关于vector的销毁】
#include <string.h>
#include <vector>
using namespace std;

class Test
{
public:
    Test() : m_pch(0) {}

    Test(const char* p)
    {
        if ( p )
        {
            m_pch = new char[strlen(p) + 1];
            strcpy(m_pch, p);
        }
    }

    ~Test()
    {
        delete[] m_pch;
        m_pch = 0;
    }

private:
    char* m_pch;
};

int main()
{	
    vector<test> vect;

    Test t("Hello World!");
    vect.push_back(t);

    return 0;
}

// 以上程序出现致命错误,由于Test默认拷贝构造函数执行的是浅拷贝,m_pch指向的内存被t和vect两次释放,程序出现崩溃。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: