我从下面的代码中得到无效点错误我不明白为什么。我要做的就是从向量中删除堆上的一些字符串:
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会创建字符串的副本吗?
答案 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
返回的指针。