【问题标题】:Requesting a specific address for the new operator请求新运营商的特定地址
【发布时间】:2012-04-06 15:30:48
【问题描述】:

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

int* array = new int[5];

然后假设我有 5 个 int 指针,都指向数组的 5 个不同整数。

 int* v1 = &array[0];
 int* v2 = &array[1]; //etc..etc

现在我已经“记住”了数组中所有整数的位置,我想将元素作为单独的整数进行管理。所以理论上如果我将我的数组指针设置为 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;

我在屏幕上看到一堆文字,上面写着“双重释放或损坏(fasttop):...

我在代码块中使用 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;
}

【问题讨论】:

  • 哦,顺便说一句,我在 cout 上没有收到“双重释放或损坏”消息,当我尝试删除 a 时才收到。
  • 听起来你真的很想创建一个内存池,这样你就不需要删除数组中的变量,而是将其标记为无效,然后在需要新分配时重用它。
  • 通过 int* v1 = array[0];你的意思是 int* v1 = &array[0]; 吗? int* v1 = 数组[0];当 array[0] 是 int 时有点荒谬。
  • 您为什么要这样做?目的是什么?可能有办法做到这一点,但我看不出这样做会得到什么。
  • 您能展示一下您是如何进行删除的,即实际的完整代码吗?

标签: c++ arrays pointers


【解决方案1】:

更正:

int *v1 = array[0];
int *v2 = array[1];

应该是

int *v1 = array;
int *v2 = array + 1;

另外,如果分配new int[5],则只能为整个数组释放内存,而不能为单个元素释放内存。

"我要保证新分配的整数是在array[0]的地址创建的"

如果是这样,你为什么要选择一个新分配的整数?只需将array 分配给v1,如上所示。

【讨论】:

    【解决方案2】:

    内存分配不能按照您使用的方式进行,您也不能以您尝试的方式释放内存。

    placement new 通过调用对象的构造函数在给定位置“创建”一个对象,但不分配内存,因此placement new 使用的内存不能通过删除来释放。在调用placement new之前应该预先分配内存,并且可以根据预先分配的方式释放内存。

    用法:Placement new。 另外,我从博客(不是我的)中找到了一个示例:Placement new

    【讨论】:

      【解决方案3】:
      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) 我看不出为什么应该在这里使用placement new,看看this SO question 看看你应该使用它的原因。在上面的示例中,int array[5];int* a = array; 就可以了。此外,在链表中的想法是可以轻松插入和删除元素,如果分配数组,则无法删除数组并期望之后能够使用内存(这将导致 UB)。所以你必须在使用数组或链表之间做出选择,你不能同时拥有(嗯,你可以在一定程度上模拟一个链表)。

      3) 就像我上面提到的,在你使用完内存后调用delete [] array;,并且一旦你释放了内存,就不要取消引用指向该内存的指针或调用删除指向该内存的指针。

      【讨论】:

        猜你喜欢
        • 2021-12-01
        • 1970-01-01
        • 2022-11-10
        • 1970-01-01
        • 1970-01-01
        • 2017-02-12
        • 1970-01-01
        • 1970-01-01
        • 2017-03-22
        相关资源
        最近更新 更多