这是我的代码:
#include <vector>
#include <stdio.h>
#include <iostream>
using namespace std;
class Foo
{
public:
Foo()
{
}
~Foo()
{
}
void Bar()
{
cout << "bar" << endl;
}
};
template <class T>
void deleteVectorOfPointers( T * inVectorOfPointers )
{
typename T::iterator i;
for ( i = inVectorOfPointers->begin() ; i < inVectorOfPointers->end(); i++ )
{
delete * i;
}
delete inVectorOfPointers;
}
int main()
{
//create pointer to a vector of pointers to foo
vector<Foo*>* pMyVec = new vector<Foo*>();
//create a pointer to foo
Foo* pMyFoo = new Foo();
//add new foo pointer to pMyVec
pMyVec->push_back(pMyFoo);
//call Bar on 0th Foo element of pMyVec
pMyVec->at(0)->Bar();
//attempt to delete the pointers inside the vector and the vector itself
deleteVectorOfPointers(pMyVec);
//call Bar on 0th Foo element of pMyVec
pMyVec->at(0)->Bar();
//call Bar directly from the pointer created in this scope
pMyFoo->Bar();
return 0;
}
我试图删除一个指向矢量的指针以及矢量内的所有指针。但是,在我尝试这样做之后,Bar仍然执行得很好......
答案 0 :(得分:5)
它会导致未定义的行为。这意味着任何事情都可能发生。这样:
*reinterpret_cast<int*>(0x12345678) = 314159;
也可能有用......那又怎么样?
答案 1 :(得分:2)
你指出的是一种不切实际的行为。 矢量和对象foo()确实已删除 ...
你只需要在pMyVec
上写下删除的矢量的地址,这样它就可以访问你之前输入的数据了。
答案 2 :(得分:2)
上面的代码有效,因为它实际上并不依赖于那里的Foo实例。没有使用实例变量,因此它永远不会访问该内存。当然,这并不能使它安全,它只是意味着它在那个特定的实例中起作用。请看以下示例:
#include <vector>
#include <iostream>
#include <string>
using namespace std;
class Foo
{
private:
std::string greet;
public:
Foo() : greet("Hello.") {}
~Foo() { cout << "Done." << endl; }
void bar() { cout << greet << endl; };
};
template <class T>
void deleteVectorOfPointers(T *vector) {
typename T::iterator i;
for (i = vector->begin(); i < vector->end(); ++i) {
delete *i;
}
delete vector;
}
int main()
{
vector<Foo *> *myVector = new vector<Foo *>();
Foo *testObj = new Foo();
myVector->push_back(testObj);
myVector->at(0)->bar();
deleteVectorOfPointers(myVector);
testObj->bar();
return 0;
}
它会像预期的那样发生段错误,因为bar()试图访问不再存在的实例变量。
答案 3 :(得分:2)
对指针调用delete会将相关内存返回给内存管理库,以便它可以重用它。
指针仍然具有原始值,但它指向不再属于您的内存 访问不属于您的内存未定义。
它可能看起来像是有效的(看起来意味着它不会崩溃并给你一个结果(可能会或可能不会很好))或者它可能会导致恶魔从你的鼻子发出咕噜声。你永远不知道哪个最好不要尝试。
答案 4 :(得分:1)
值得考虑使用ptr_vector而不是存储指针的向量。
http://www.boost.org/doc/libs/1_48_0/libs/ptr_container/doc/ptr_vector.html
您应该记住,访问已删除的数据并不总是指向segfault。有时老年人没有新数据。删除没有清除内存空间。
示例内存空间:
[X _] [Y] [ž
删除Z后:
[x _] [y] [ Z ]
Z 可以有效一段时间,但它是一个未定义的行为,因为 Z 现在只是垃圾。
答案 5 :(得分:0)
这个CAN工作正常只是因为你的函数Foo :: Bar真的永远不会访问对象*这个。