请求新运营商的特定地址

时间:2012-03-22 03:29:05

标签: c++ arrays pointers

假设我要分配一个整数数组。

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

3 个答案:

答案 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;并且不要将指针解引用到该内存中,或者在释放内存后调用指向该内存的指针。