正确使用new/delete
Proper use of new/delete
作为我上一个问题的续集,我想问一下我在下面的代码中做错了什么。
代码为,例如
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;
}
但是当我运行它时,myvector返回空,除非我注释掉delete
行。
我做错了什么?
您只希望在完全使用完对象后删除它。一旦你删除了它,你就不应该试图再次引用它。
在典型情况下,您只想将对象本身(而不是指向对象的指针)放入vector中。这将在将对象添加到vector时创建该对象的副本,并在从vector中删除该对象或vector本身被销毁时自动销毁该对象。
如前所述,当您已经释放内存时,您无法访问或更改内存。必须注意在析构函数(或额外的函数)中删除对象。下面是这样做的代码片段:
// 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
}
}
调用newVar的析构函数,并在调用delete时将new分配的内存返回给堆。
此时不应该调用delete。在myclass1的析构函数或其他成员函数中执行。
最佳实践是:存储在vector值或智能指针中,如boost::shared_ptr<>。智能指针适合你的情况。你甚至不用担心删除myvector的元素,因为当myvector被解构时,它们会被正确地解构。示例代码为:
void myclass1::myfun()
{
myvector.push_back(boost::shared_ptr<myclass2>(new myclass2()));
}
c++不是c#或Java或其他什么。您正在使用原始指针,您可能不应该这样做。当您删除刚刚分配的对象时,它就消失了,不能再使用了。在vector中存储指向它的指针,而该指针似乎在函数作用域之外持续存在,这是一个错误。
您在堆上创建了myclass2
的实例,然后将指向它的指针放入向量中。当你执行delete newVar;
时,你正在破坏你刚刚创建的实例。但是你的vector仍然有一个指向对象所在位置的指针,而这个指针已经失效了。
当你不再需要堆上的对象时,你应该只调用delete
。
选项如下:
-
不要删除对象。这意味着你必须在程序的其他地方删除它,当所有的东西都用完了。这可能很难协调,所以你需要使用智能指针。如果您正在编译c++0x,则可以在Boost库或标准库中找到
shared_ptr
。下面是在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; }
-
不要在堆上分配对象。相反,只需用
myclass
的实例填充向量,而不是指向myclass
的指针。现在你的矢量将是std::vector<myclass2>
如果可以选择,第二个选项是最好的。当vector被销毁时,myclass2的实例将被销毁,这就减少了跟踪它们的麻烦。
- g++用户定义的动态链接库上的全局new和delete运算符
- 体系结构x86_64的未定义符号:std:terminate(),typeinfo,运算符delete[],运算符new
- 为什么 std::vector 使用 std::分配器而不是运算符 new 和 delete?
- 重载 new 和 delete 会导致 valgrind 错误
- 基类指针:在哪里使用 new 和 delete
- C++:为什么可以在没有事先使用 new 的情况下在指向结构的指针上使用 delete?
- 重载运算符 new 和运算符 delete 带有三个参数
- 如果我为一个类编写new和delete运算符,我是否必须编写它们的所有重载
- new[] / delete[] 并在C++中抛出构造函数/析构函数
- QQuickView new-delete-type-mismatch
- 使用重载的 new 和 delete 运算符跟踪已用内存
- 创建 myNew/myDelete 以替换 new/new[]/delete/delete[]
- 为多线程环境包装 c++ new/delete 的安全/好方法
- C++ VS:多 DLL 解决方案中的'new'和'delete'覆盖
- 如何使用 new 和 delete 与 OpenGL 的缓冲区对象一起使用?
- c++ 运算符 new[]/delete [] 是否调用运算符 new/delete?
- 继承类上的运算符new和delete.操作员删除未执行
- 在不同的编译器版本中调用new[]和delete[]
- `delete []`on`int*````new'''给出了malloc错误
- C++内存分配失败(使用 new & delete)