假设我要分配一个整数数组。
int* array = new int[5];
然后假设我有5个int指针,都指向数组的5个不同的整数。
int* v1 = &array[0];
int* v2 = &array[1]; //etc..etc
现在我已经“记住”了数组中所有int的位置,我想将这些元素作为单个整数来管理。所以理论上如果我然后将我的数组指针设置为NULL ...
array = NULL;
理论上我不必担心,因为我的所有v1和v2指针都指向数组中的所有元素。那么问题就像是我完成了v2。所以我想删除v2以释放这4个字节。
delete v2;
不幸的是,当我尝试这样做时,会发生不好的事情。我假设因为内存分配表说“嘿,你不能删除那个空间,因为它当前属于一个int数组的一部分!”
那很好,我想说
delete [] array;
但如果我这样做,我想确保当我这样做时......
int* v1 = new int;
我想保证在array [0]的地址创建新分配的整数。那么有没有办法指定创建新值的位置?或者我可以以某种方式控制内存列表?
我试图通过调用类似......
之类的东西来使用放置运算符int* v1 = new((void*)&array[0]) int;
但是当我用删除操作符删除数组然后尝试通过取消引用来访问v1时...说
cout<<*v1;
我在屏幕上看到一堆文字,上面写着“双重免费或腐败(快速登陆):......
”我在代码块中使用Ubuntu 11.04和g ++编译器。
另外,仅供参考,我查看Create new C++ object at specific memory address?,这是我获得有关展示位置运算符的信息的地方,但它似乎无法按照我需要的方式工作。
#include <iostream>
using namespace std;
int main()
{
int *array = new int[20];
for(int i=0;i<4;i++)
{
array[i] = i;
}
int* a = new ((void*)&array[0]) int;
int* b = new ((void*)&array[1]) int;
int* c = new ((void*)&array[2]) int;
int* d = new ((void*)&array[3]) int;
int* e = new ((void*)&array[4]) int;
cout<<*a<<endl;
cout.flush();
delete[] array;
cout<<*a;
delete a;
delete b;
delete c;
delete d;
delete e;
return 0;
}
答案 0 :(得分:0)
更正:
int *v1 = array[0];
int *v2 = array[1];
应该是
int *v1 = array;
int *v2 = array + 1;
此外,如果您分配new int[5]
,则只能释放整个阵列的内存,而不能释放单个元素。
“我想保证新分配的整数是在array [0]”
的地址创建的如果是这种情况,为什么要选择新分配的整数?只需将array
分配给v1
,如上所示。
答案 1 :(得分:0)
内存的分配不会像您使用的那样工作,也不会以您尝试的方式释放内存。
通过调用对象的构造函数,放置new在给定位置“创建”一个对象但不分配内存,因此放置new使用的内存不能通过删除释放。应该在调用placement new之前预先分配内存,并且可以根据预分配的方式释放内存。
用法:Placement new。 另外,我在博客(不是我的)中找到了一个例子:Placement new
答案 2 :(得分:0)
delete v2;
您不应删除使用展示位置新分配的元素,在完成后一次释放所有内存,例如delete [] array;
(更多detailed explanation)。
更新您的代码:
#include <iostream>
using namespace std;
int main()
{
int *array = new int[20];
for(int i=0;i<5;i++) // Still leaves garbage in rest of array
{
array[i] = i;
}
int* a = new (array) int;
// int* a = new(&array[0]) int;
int* b = new (array + 1) int;
int* c = new (array + 2) int;
int* d = new (array + 3) int;
int* e = new (array + 4) int;
cout << *a << " " << *b << " " << *c << " " << *d << " " << *e << endl;
delete[] array;
}
指点:
1)cout.flush();
是不必要的,因为std::endl
已经调用了flush()
。
2)我认为没有理由在这里使用贴身新品,请查看this SO question以查看您应该使用它的原因。在上面的示例中,int array[5];
和int* a = array;
会没问题。此外,在链表中,想法是可以轻松插入和删除元素,如果分配数组,则无法删除数组,并且希望以后能够使用内存(这将导致UB)。所以你必须在使用数组或链表之间做出选择,你不能同时拥有它们(好吧,你可以在某种程度上模拟链接列表)。
3)就像我上面提到的那样,在你完成使用内存之后调用delete [] array;
并且不要将指针解引用到该内存中,或者在释放内存后调用指向该内存的指针。