正确使用new / delete

时间:2011-08-18 12:22:43

标签: c++

作为我previous question的续集,我想在下面的代码中询问我做错了什么。

代码是,例如

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行。

我做错了什么?

5 个答案:

答案 0 :(得分:3)

您只想在完成使用后删除该对象。删除后,不应再尝试再次引用它。

在典型情况下,您只想在对象中放置对象本身(而不是指向对象的指针)。当您将对象添加到向量时,它将创建对象的副本,并在从向量中删除对象时自动销毁对象,或者向量本身被销毁。

答案 1 :(得分:2)

如前所述,当您已经释放内存时,您无法访问或更改内存。您必须注意在析构函数中删除对象(或额外的函数)。这是一个可以做到这一点的片段:

// 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
  }
}

答案 2 :(得分:2)

调用newVar的析构函数,并在调用delete时将new分配的内存返回给堆。

此时不应调用delete。在myclass1的析构函数或其他成员函数中执行。

最佳做法是:存储在向量值或智能指针中,例如boost :: shared_ptr&lt;&gt;。智能指针适合您的情况。你甚至可以不用担心删除myvector的元素,因为当myvector被破坏时它们会被正确地破坏。 示例代码是:

void myclass1::myfun()
{
   myvector.push_back(boost::shared_ptr<myclass2>(new myclass2()));
}

答案 3 :(得分:1)

C ++不是C#或Java或其他什么。您正在使用原始指针,您可能不应该这样做。删除刚刚分配的对象时,它已经消失,不能再使用了。在向量中存储指向它的指针是一个错误。

答案 4 :(得分:1)

您在堆上创建了myclass2的实例,然后将指针放入向量中。执行delete newVar;时,您正在销毁刚刚创建的实例。但是你的向量仍然有一个指向对象所在位置的指针,指针不再有效。

当你不再需要堆上的对象时,你应该只调用delete

您的选择如下:

  1. 不要删除该对象。这意味着当一切都已完成使用时,您必须在程序中的某个其他位置删除它。这可能很难协调,因此您需要使用智能指针。如果要编译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;
    }
    
  2. 不要在堆上分配对象。相反,只需使用myclass的实例填充向量,而不是指向myclass的指针。现在你的矢量将是std::vector<myclass2>

  3. 如果您有选择,第二个选项更可取。每当矢量被销毁时,你的myclass2实例都会被销毁,这减轻了跟踪它们的麻烦。