从向量中删除取消引用的元素
Posted
技术标签:
【中文标题】从向量中删除取消引用的元素【英文标题】: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;
【问题讨论】:
【参考方案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 没有将分配的值放入向量中;它正在输入值,然后 泄漏内存 a
、b
和 c
指向的。来电:
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<>::push_back()
复制了它的参数。你应该delete
createObjects()
范围结束前的指针。
也就是说,我不明白您为什么一开始就使用动态分配。如果你能避免这种情况,请这样做(你可以使用像std::unique_ptr<>
这样的智能指针,或者更好的是使用普通的旧double
s)。
【讨论】:
感谢您的回复。我已经修改了我的代码以删除方法末尾的指针。我现在在最后的向量上调用 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
时,我的静态声明的对象被复制到了堆内存中。感谢您的帮助。以上是关于从向量中删除取消引用的元素的主要内容,如果未能解决你的问题,请参考以下文章