【问题标题】:C++ delete vector of pointersC++ 删除指针向量
【发布时间】:2011-12-28 18:51:55
【问题描述】:

这是我的代码:

#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 仍然执行得很好......

【问题讨论】:

  • 删除后访问对象成员是未定义的行为,这不是测试代码是否有效的方法。
  • 所以...对象成员在删除指向该对象的指针后仍然可以访问?
  • 它是未定义的,这意味着如果没有任何东西覆盖曾经存在的内存,则数据可能是可访问的。如前所述,不要依赖未定义的行为来测试您的代码。
  • 嗯,不是吗?这就是为什么指针在删除后通常设置为 NULL(即阻止代码使用!)

标签: c++ pointers vector


【解决方案1】:

它会导致未定义的行为。这意味着任何事情都可能发生。这个:

*reinterpret_cast<int*>(0x12345678) = 314159;

也可以工作...那又怎样?

【讨论】:

    【解决方案2】:

    您指出的是一种未定义的行为。 向量和对象 foo() 真的被删除了...

    您只需将已删除向量的地址写在pMyVec 上,这样它就可以访问您之前放入的数据。

    【讨论】:

      【解决方案3】:

      上面的代码有效,因为它实际上并不依赖 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() 试图访问一个不再存在的实例变量。

      【讨论】:

      • 取决于很多东西,它可能会或可能不会出现段错误。这就是为什么它被称为未定义的行为。
      • 确实如此。关键是OP的代码根本没有触及向量中的对象。该字符串作为常量存储在其他地方,并且不涉及任何实例变量,因此它基本上是一个原始函数调用功能。因此,期望它不会出错更为合理,即使它会更好。
      【解决方案4】:

      在指针上调用 delete 会将关联的内存返回给内存管理库,以便它可以重新使用它。

      指针仍有原来的值,但它指向的内存不再属于你。
      访问不属于您的内存是未定义的。

      它可能看起来有效(看起来意味着它不会崩溃并给你一个结果(可能好也可能不好))或者它可能会导致恶魔从你的鼻子里发出咕噜声。你永远不知道哪个最好不要尝试。

      【讨论】:

        【解决方案5】:

        值得考虑使用 ptr_vector 代替 vector 来存储指针。

        http://www.boost.org/doc/libs/1_48_0/libs/ptr_container/doc/ptr_vector.html

        您应该记住,访问已删除的数据并不总是直接指向段错误。有时老的地方没有新数据。删除没有清除内存空间。

        一个示例内存空间:

        [x_][y][Z]

        删除Z后:

        [x_][y][Z]

        Z 可以在一段时间内有效,但它是一种未定义的行为,因为 Z 现在只是一个垃圾。

        【讨论】:

          【解决方案6】:

          这可以正常工作,因为你的函数 Foo::Bar 真的从不访问对象 *this。

          【讨论】:

            猜你喜欢
            • 2013-07-02
            • 1970-01-01
            • 2020-06-24
            • 2013-09-24
            • 2012-08-12
            • 2010-09-08
            • 2015-08-09
            • 1970-01-01
            相关资源
            最近更新 更多