As a sequel of my previous question, I would like to ask what I am doing wrong in the following 开发者_JAVA技巧code.
The code is, for example
void myclass1::myfun()
{
myclass2* newVar = new myclass2();
/* other code and stuff */
myvector.push_back(newVar); // myvector is a member of myclass1 and is a std::vector<myclass2*>
delete newVar;
}
but when I run it, myvector returns empty, unless I comment out the delete
line.
What am I doing wrong?
You only want to delete the object when you're completely finished using it. Once you delete it, you shouldn't attempt to refer to it again.
In a typical case, you just want to put objects themselves (rather that pointers to objects) in your vector. That will create a copy of the object when you add it to the vector, and automatically destroy the object when you erase it from the vector or the vector itself is destroyed.
As already said, you cannot access or change memory when you have freed it already. You must take care of deleting your object in your destructor (or an extra function). Here's a snippet that would do that:
// this function adds the object
`void MyClass1::AddFun()
{
myClass2* Ptr = new myClass2(); // create new object via new-operator
myvector.push_back(Ptr);
}
// this function clears the entire vector
void MyClass1::ClearAllContent()
{
while (myvector.empty() == false)
{
delete myvector[myvectory.size() - 1]; // free the last object in your vector
myvector.pop_back(); // pop_back reomves the "empty"-pointer
}
}
The destructor of newVar is called and memory allocated by new is returned back to the heap when you call delete.
You shouldn't call delete at this point. Do it in destructor of myclass1 or in another member function.
The best practise is: Store in vector values or smart pointers like boost::shared_ptr<>. Smart pointers are for your case. You can even don't worry about deleting elements of myvector because they'll be destructed correctlly when myvector is destructed. the example code is:
void myclass1::myfun()
{
myvector.push_back(boost::shared_ptr<myclass2>(new myclass2()));
}
C++ is not C# or Java or whatever. You are using raw pointers, which you should probably not do. When you delete the just-allocated object, it's gone and cannot be used anymore. That you store a pointer to it in the vector that appears to persist beyond the function's scope is an error.
You created an instance of myclass2
on the heap and then put a pointer to it into a vector. When you do delete newVar;
you are destroying the instance that you just created. But your vector still has a pointer to where the object was and that pointer isn't valid any more.
You should only be calling delete
when you don't need the object on the heap any more.
Your options are as follows:
Don't delete the object. This means that you'll have to delete it at some other point in your program, when everything has finished using it. That might be difficult to co-ordinate and so you'd need to use a smart pointer. You can find
shared_ptr
in either the Boost library or the standard library if you're compiling for c++0x. Here's how you'd use it in c++0x:#include <vector> #include <memory> #include <algorithm> #include <iostream> int main(int argc, const char* argv[]) { typedef std::vector<std::shared_ptr<int>> Vector; Vector v = { Vector::value_type(new int(2)), Vector::value_type(new int(5)) }; std::for_each(v.begin(), v.end(), [](Vector::value_type x) { std::cout << *x << std::endl; }); return 0; }
Don't allocate the object on the heap. Instead, just fill the vector with instances of
myclass
instead of pointers tomyclass
. Now your vector will be astd::vector<myclass2>
.
The 2nd option is preferable if you have the choice. Your instances of myclass2 will be destroyed whenever the vector is destroyed which alleviates the hassle of keeping track of them.
精彩评论