C ++无效指针错误

时间:2013-02-22 19:29:38

标签: c++ pointers

我从下面的代码中得到无效点错误我不明白为什么。我要做的就是从向量中删除堆上的一些字符串:

void func() {
    vector<string>* vec = new vector<string>;
    vec->push_back(*(new string("1")));
    vec->push_back(*(new string("2")));

    for(vector<string>::iterator itr = vec->begin(); itr != vec->end(); ++itr)
    {
        string* ptr = &(*itr);
        delete(ptr);
    }
}

编辑:是因为push_back会创建字符串的副本吗?

3 个答案:

答案 0 :(得分:6)

您的错误是因为元素未动态分配; vector 是。你要做的是:

void func() 
{
    vector<string*> vec;
    vec.push_back(new string("1"));
    vec.push_back(new string("2"));

    for(vector<string*>::iterator itr = vec.begin(); itr != vec.end(); ++itr)
    {
        string* ptr = *itr;
        delete(ptr);
    }
}

但老实说,我认为没有理由这样做。在编写代码时,您的代码不仅会尝试删除它从未实际分配过的内存,而且会泄漏 所做的分配。

> 令人不安的原始内容),但有些东西告诉我你有这样的需要。

答案 1 :(得分:4)

首先,行

vec->push_back(*(new string("1")));

导致内存泄漏。从new string("1")返回的值是指向新分配的字符串对象的指针。但是当您取消引用它并将其插入向量时,将创建并插入堆分配对象的副本。但是,最初在堆上分配的实际字符串对象会泄露。

实际上,您的向量是按值存储字符串对象,而不是指向字符串对象的指针。插入到向量中的字符串对象的副本不是堆分配的对象(不是分配有new的对象)。当然,您不能delete未使用new分配的内容。因此,当您调用delete(ptr)时,您将导致未定义的行为。

你似乎想要的是:

vector<string*>* vec = new vector<string*>;

但是,总的来说,我没有看到为什么要在堆上分配所有内容的任何令人信服的理由。在C ++中,最好在可行的情况下使用堆栈分配和具有值语义的容器,除非您有一些理由需要堆分配(例如,多态对象的容器,在这种情况下,您应该使用智能指针)。通常,当新的C ++程序员在整个地方使用堆分配的对象和new关键字时,这表明它们很难音译从Java或C#等托管语言导入的编程风格。

答案 2 :(得分:3)

不,你不是 - 你的矢量存储string个对象,而不是指向string个对象的指针。这就是为什么你的*调用中有push_back的原因 - 你正在取消引用返回的指针。

您正在添加使用new创建的动态字符串的副本,并且该动态字符串已丢失,因为您从未存储new返回的指针。