【问题标题】:Understanding dynamic objects ("new") in C++了解 C++ 中的动态对象(“新”)
【发布时间】:2012-09-09 01:21:00
【问题描述】:

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

我声明了一个变量

int x = 4;

然后说

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

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

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

【问题讨论】:

  • 不幸的是,您程序中的几乎所有内容都是未定义的行为,并且您的大多数假设都是错误的。

标签: c++ memory


【解决方案1】:

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

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 中。但是,在下一行中,您会覆盖变量并丢失指向动态整数的指针。您已经泄露了该对象,并且无法再恢复它。

【讨论】:

    【解决方案2】:
    int* ptr = new int;
    ptr = &x;
    

    ptr 指向堆中的一块内存

    不,它没有。赋值后指向变量x的地址,变量automatic storage。您丢失了最初由ptr 指向的动态分配的int 的句柄,因此您不能再删除它。 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";
    
    }
    

    【讨论】:

      【解决方案3】:

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

      所以4 仍然在它们相同的地址,在堆栈上,只是在您执行ptr=&amp;x; 之后它也被ptr 引用。

      【讨论】:

      • @user1247384 不要忘记为您认为有用的答案投票,并接受其中一个
      猜你喜欢
      • 1970-01-01
      • 2020-10-29
      • 1970-01-01
      • 2021-06-23
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      • 2010-11-03
      • 1970-01-01
      相关资源
      最近更新 更多