2

我正在尝试更深入地了解新运营商。我确实理解它从堆中分配内存并返回指向内存的指针这一事实。我的问题是,一旦我得到指针并使用它来存储另一个指向另一个声明变量的指针,值复制或指向的值是如何发生的?所以例如

我声明一个变量

int x = 4;

int* ptr = new int;
ptr = &x;

ptr 从堆中指向一块内存。x 定义在拥有单独内存块的堆栈中。ptr 和 x 的地址相同。如果我删除 ptr,x 仍然有效,因为它仍然存在于内存中。当我说 *ptr 时,我正在寻找 ptr 指向的值,在这种情况下是 4。我的问题是 4,它在哪里。它是否存在于两个单独的内存块中。一个由 x 表示,另一个是我刚从 new 得到的。这个过程是如何发生的?4 如何在两个块之间传输,或者我错过了什么?请帮忙。

另外,当我说 ptr = &x 时,是按位复制。换句话说,我是否永远失去了刚刚通过堆访问的内存?

4

3 回答 3

6
int* ptr = new int;
ptr = &x;

ptr 从堆中指向一块内存

不,它没有。赋值后指向变量的地址,变量x自动存储int您已经丢失了最初指向的动态分配的句柄ptr,因此您不能再删除它。4不会通过任何内存“块”传输。当您取消引用时ptr,您将获得由 x 引用的变量,其中包含值4

试试这个例子:

#include <iostream>

int main()
{

  int x = 4;
  int* ptr = new int;
  ptr = &x;  // lose handle on dynamically allocated int: MEMORY LEAK
  std::cout << (*ptr) << "\n";
  x += 1;
  std::cout << (*ptr) << "\n";
  (*ptr) += 1;
  std::cout << x << "\n";

}
于 2012-09-16T17:09:29.057 回答
2

如您所见,您可以指向ptr任何您想要的地址,但这并不意味着它是安全的。在这里,您正在执行错误的内存操作,因为分配的内存new是孤立的,而不是由ptr. 这是语言允许的,但不安全。

所以4仍然在他们相同的地址,在堆栈上,只是它也被 a ptrafter you did引用ptr=&x;

于 2012-09-16T17:14:07.463 回答
2

忘记“堆栈”和“堆”。这对于您需要了解的内容并不重要。

C++ 中的对象具有三种不同的存储类之一:静态、动态和自动。

自动和静态对象是非引用变量的值。更准确地说,命名空间范围内的变量和块范围内的静态变量保存静态对象,而块范围内的非静态变量保存自动对象。这些对象的生命周期取决于它们在源代码中的位置:

// file.cpp

int a;             // static, global (= "namespace scope")

void foo()
{
    static int b;  // static, block scope

    int c;         // automatic (always block scope)
}


相比之下,动态对象正是那些作为new表达式的结果而创建的对象。动态对象本身永远不是变量。您只能通过指针(它本身是一个对象)或通过引用变量(并且引用永远不是对象)来获取它们:

Foo * p = new Foo;
Foo & q = *new Foo;  // NEVER do this!

动态对象一直存在,直到您通过指向它们的指针明确删除它们:

delete p;    // normal
delete &q;   // works, but insane

在您的情况下,new int创建一个新的动态对象类型int,并将指向该对象的指针存储在变量中ptr。但是,在下一行中,您将覆盖变量并丢失指向动态整数的指针。您已经泄漏了对象,并且无法再恢复它。

于 2012-09-16T17:15:11.560 回答