【问题标题】:Can a pointer be placed on heap memory (C++)?可以将指针放在堆内存(C++)上吗?
【发布时间】:2019-10-07 03:27:03
【问题描述】:

我编写了一些代码,试图在空闲存储(堆内存)上创建一个指针。我认为这是不可能的,但我无论如何都尝试了。

下面的代码基本上是在堆上创建一个指针向量,然后使向量中的这些指针指向堆上的一些整数。我想知道称为 vec 的向量中的那些指针是否在堆上?我还想知道在使用这样的向量时释放分配空间的正确方法是什么。最后一个删除语句使程序崩溃,所以我将其注释掉。不知道有没有内存泄漏。

    vector<int*> *vec = new vector<int*>();
    vec->push_back(new int(1));
    vec->push_back(new int(2));
    vec->push_back(new int(3));
    cout << (*vec)[0] << " " << (*(*(vec))[0]) << endl;
    cout << (*vec)[1] << " " << (*(*(vec))[1]) << endl;
    cout << (*vec)[2] << " " << (*(*(vec))[2]) << endl;
    delete (*vec)[0];
    delete (*vec)[1];
    delete (*vec)[2];
    //delete [] vec;

【问题讨论】:

  • //delete [] vec; 是您需要的未定义行为 delete vec; 不是 delete [] vec;
  • delete[] 用于匹配您从未使用过的new[]。就这么简单。
  • 您不创建指针。一个指针指向内存区域。这些可以包含对象,这些对象确实是被构造的。
  • FWIW,你几乎不想做vector&lt;int*&gt; *vec = new vector&lt;int*&gt;();。向量本身会对它持有的对象使用动态分配,因此您不需要动态分配向量。
  • 每个 c++ 套件都有可能是唯一的实现细节。我的 Lubuntu 18.04 64 位,g++ v7 将 sizeof(std::vector) 报告为 24 字节,不管 T,不管有多少元素。您的系统 std::vector 可能不同。

标签: c++ pointers vector heap-memory stack-memory


【解决方案1】:

任何变量都可以在堆中创建,包括指针。 也就是说,在 C++ 级别,您无法控制创建内存的确切位置。

【讨论】:

  • 有人告诉我,当使用堆内存时,指针在堆栈中,它们指向堆中的变量。所以我只想澄清一下,指针可以在堆上。
  • 当您在 C++ 级别说您无法控制创建内存的确切位置时,您的意思是什么。我的意思是当你使用 new 关键字时,你知道它在堆上。
  • c++ 没有正式的 heapstack。这些是实现细节。
  • 您的老师可能将事情过于简单化为一个非常常见的情况,即在堆栈上创建一个局部变量而不是包含指向堆的指针(通常是在引入动态内存分配时使用的第一个示例。)希望以后能进一步解释这一概念。
  • 你仍然不知道内存是在哪里创建的。 Placement new 在预分配的内存中创建数据,但您不知道该内存在哪里。了解内存的唯一方法是检查指针并根据 RSP 比较以某种方式推断它不在当前堆栈上。但这没用。
【解决方案2】:

了解指针最重要的一点是指针没有什么特别之处。

与所有其他矢量元素一样,vec 的元素位于免费存储中,因为这是矢量保存它们的地方。

如果你想在免费存储中手动创建一个int*,你会说new int*,它当然会返回那个指针的地址,例如

int** pointer = new int*(nullptr);

但是,在实践中这样做没有什么意义——我认为在我 20 多年的 C++ 中,我没有见过有人使用它。

【讨论】:

    【解决方案3】:

    c++在堆上创建指针的方式如下: int** pointerToPointer = new int*;

    int** 类型可以被读取为指向指针的指针。然后我们使用new在堆上分配一块int*(int指针)类型的数据。

    【讨论】:

    • “c++ 方式...” 不是。
    • 为什么? new 运算符是 C++ 标准指定的最低级别。如果您使用malloc,那么它将是 C 方式。
    • 为此,是的。但是在 c++ 中实现了更好的机制。 newdelete 被认为是最后的手段。
    • 即- 现代 C++ 希望我们将时髦的指针包装到智能指针或容器中,这样我们应该(几乎)永远不需要再次使用 new/delete。相反,让对象的作用域、它的生命周期来处理这个问题,这样我们就不会在留下悬空指针的同时到处泄漏内存。
    • 我完全理解你在说什么,但是我觉得好的做法超出了这个问题的范围。
    【解决方案4】:

    如果你想为一个整数分配内存,你可以说new int;,就像你在这里所做的那样。

    new 关键字将接受任何(非空)类型。所以如果你想分配一个指针(类型为int*),你可以说new int*;

    一个(非常做作的)示例可能如下所示:

    int thing = 7;
    int **ptr = new int*(&thing);
    std::cout << "**ptr = " << **ptr << std::endl;
    

    请注意,由于new 将返回指向我们分配的任何类型的地址(在本例中为int*),因此我们需要将其分配给int** 变量。


    话虽如此,您不太可能需要分配原始new int*。如果您正在处理动态分配的多维数组,您很可能会遇到类似的情况。

    但在任何这些情况下,我强烈建议使用更现代的内存管理方法 Smart Pointers

    【讨论】:

      猜你喜欢
      • 2016-03-06
      • 2013-11-07
      • 1970-01-01
      • 1970-01-01
      • 2014-09-05
      • 2016-04-03
      • 1970-01-01
      • 2015-04-21
      • 2017-06-19
      相关资源
      最近更新 更多