【问题标题】:Deleting dereferenced elements from vector从向量中删除取消引用的元素
【发布时间】:2012-02-16 00:42:37
【问题描述】:

我使用 new 创建了对象,但是在将它们添加到向量之前取消了对它们的引用。尽管在互联网上拖网,但我无法弄清楚如何在这些项目上调用删除。我只想使用我不想(例如)使用 Boost 库的标准 C++ 和 STL 来做到这一点。

如您所见,a、b 和 c 失去了作用域,剩下的就是我认为是向量中的副本。我该如何删除这些。我不想在数组中存储指针,因为我需要向 API 函数传递一个双精度数组。

请人 - 我如何删除这些对象?

#include <iostream>
#include <vector>

using namespace std;

vector<double> vectorDouble;
void createObjects();

void createObjects() {
    double* a=new double(13);
    double* b=new double(14);
    double* c=new double(15);
    //a,b and c are not contiguous memory blocks
    cout << "memory location of a: " << a << endl;
    cout << "memory location of b: " << b << endl;
    cout << "memory location of c: " << c << endl;

    vectorDouble.push_back(*a);
    vectorDouble.push_back(*b);
    vectorDouble.push_back(*c);
}

int main() {
    createObjects();
    //the memory addresses are contiguous 8 byte chunks
    cout << "vector memory at 0: " << &(vectorDouble[0]) << endl;
    cout << "vector memory at 1: " << &(vectorDouble[1]) << endl;
    cout << "vector memory at 2: " << &(vectorDouble[2]) << endl;

    //get pointer to the 2nd element
    double *P=&(vectorDouble[1]); 

    //dereference and look inside - two memory locations both contain the value 14
    cout << "vector Pointer P ["<< P <<"] contains " << *P <<endl;

    //Which should I call delete on? I have lost reference to the original pointers.
    //How should I call delete on the vector?

    cout << "deleting pointer that references 2nd vector element" << endl;
    delete P; //********* CRASH **********
    cout << "Done deleting" << endl;
}

【问题讨论】:

    标签: c++ stl vector


    【解决方案1】:

    您需要删除的对象不在向量中,因为您的向量元素不是用 new 创建的。当您在 push_back 中使用取消引用运算符时,您只是将 malloc 的 double 的副本而不是实际分配的 double 传递给向量。

    您实际上只是在泄漏它们 - 您的代码可以在不分配双精度的情况下运行良好:

    void createObjects() {
        vectorDouble.push_back(13);
        vectorDouble.push_back(14);
        vectorDouble.push_back(15);
    }
    

    【讨论】:

      【解决方案2】:

      正如每个人所指出的,没有任何理由在您的程序中调用new

      void createObjects() {
          vectorDouble.push_back(13);
          vectorDouble.push_back(14);
          vectorDouble.push_back(15);
      }
      

      但是,假设您确实有理由致电new。 (我无法想象它可能是什么,但让我们假设你是个天才)。以下是你的做法:

      void createObjects() {
          double* a=new double(13);
          double* b=new double(14);
          double* c=new double(15);
          //a,b and c are not contiguous memory blocks
          cout << "memory location of a: " << a << endl;
          cout << "memory location of b: " << b << endl;
          cout << "memory location of c: " << c << endl;
      
          vectorDouble.push_back(*a);
          vectorDouble.push_back(*b);
          vectorDouble.push_back(*c);
      
          delete a;
          delete b;
          delete c;
      }
      

      您看,push_back 不会将指针的副本放入向量中,而是将对象的副本放入向量中。一旦你复制了你的对象,那么你的对象的内存就没有持续的作用,并且可以被销毁。

      【讨论】:

      • 好的,我调用new的原因是这个程序实际上代表了我要编写的真实程序:
      • 好的,我调用 new 的原因是这个程序实际上代表了我要编写的真实程序:它是 DirectX 程序,我想要一个 D3DX10_SPRITE 数组,它需要传递给API 函数 DrawSpritesBuffered。正如你所指出的,我可以很容易地创建这些对象而不使用 new,这个问题就会消失。但是我应该在堆栈上创建可能占用 20k 的对象吗?
      【解决方案3】:

      函数 createObjects 没有将分配的值放入向量中;它正在输入值,然后 泄漏内存 abc 指向的。来电:

      vectorDouble.push_back(*a);
      

      a 指向的值存储在向量中(*a 取消引用指针,您可能已经知道了)。一旦该函数返回,指针就会丢失。您无法从向量中检索它们。您要么需要创建一个指向双精度的指针向量,要么(更有可能)甚至不分配值;只需存储双打。

      【讨论】:

        【解决方案4】:

        我想我有问题,在:

        vectorDouble.push_back(*a);
        vectorDouble.push_back(*b);
        vectorDouble.push_back(*c);
        

        您将 a、b 和 c 作为值传递,因此数组实际上并不包含您创建的变量(这就是为什么它们现在具有不同的内存地址,它们是变量内容的副本!)。然后你可以删除方法内的变量,不要在方法内使用指针或使用双*向量。

        【讨论】:

          【解决方案5】:

          您的泄漏在createObjects() 中,因为std::vector&lt;&gt;::push_back() 复制了它的参数。你应该deletecreateObjects()范围结束前的指针。

          也就是说,我不明白您为什么一开始就使用动态分配。如果你能避免这种情况,请这样做(你可以使用像std::unique_ptr&lt;&gt; 这样的智能指针,或者更好的是使用普通的旧doubles)。

          【讨论】:

          • 感谢您的回复。我已经修改了我的代码以删除方法末尾的指针。我现在在最后的向量上调用 clear() 。我假设现在没有内存泄漏。请问最后一个问题;我在向量中的双打现在是在堆上还是在栈上?
          • 您根本不需要调用v.clear(),除非您希望从向量中删除所有元素。如果你说在范围内double *a = new double(13),那么在范围结束时你必须说delete a,当然除非你将a传递给另一个声称对a负责的函数或对象,这样它本身就会@987654332 @ 一种。您可以看到这并不简单,这就是为什么在 C++ 中我们总是希望尽可能避免动态分配。我不知道你为什么对v.push_back(13.0) 不满意。
          • 好的,我会选择v.push_back(object)。 Object 不会被声明为指针,也不会使用new。它将在创建它的方法的范围之外持续存在,因为向量已经复制了它并正在管理该副本。这使生活变得更加轻松,因为我不必新建/删除它。我暂时接受我不理解向量是如何管理内存的,但我只能假设当我使用push_back 时,我的静态声明的对象被复制到了堆内存中。感谢您的帮助。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-05-05
          • 2020-05-22
          • 1970-01-01
          • 2012-03-13
          • 1970-01-01
          • 2020-07-01
          • 2019-01-07
          相关资源
          最近更新 更多