【问题标题】:Memory assignment dilema in C++C++中的内存分配困境
【发布时间】:2023-03-25 18:37:01
【问题描述】:

将一个 C++ 函数视为:

A* dum()
{
  A* a = new A()
  doSomethingOnA()
  return a;
}

现在dum() 被称为

A* b;
b = dum();

我的问题是我们是否也需要为b 分配内存?

编辑:如果我这样做:

bool dum(A* a)
{
  // A* a = new A() -- Is this needed?
  doSomethingOnA()
  return 1;
}

而dum被称为

A* b = new A()
dum(b);

【问题讨论】:

  • “分配内存”是什么意思?
  • 不,b 是来自dum()a,因为a 指向的是数据,而b 将指向同一个地址然后a
  • @Borgleader - 我的意思是执行 b= new A()
  • 您不想为 b 分配内存,因为 dum() 会这样做。在调用 dum() 之前为 b 分配内存会导致内存泄漏,除非您释放它。
  • @MayankJain 你为什么要使用原始指针和new()?在 c++ 中通常不需要这样做。你可能对 java 或 c# 的概念感到困惑。

标签: c++ memory-management


【解决方案1】:

从 RAII 的角度来看,您不应在 dum 内分配并返回原始指针。

更好的选择是:

  • std::unique_ptr dum();
  • std::shared_ptr dum();
  • 空虚(A&);

前两个返回一个托管指针,而第三个期望一个可能是堆栈或堆变量的引用。

另一个不错的选择是按值返回(如果 `A 写得好,这应该会给出编译器优化的代码):

  • dum();

另见:

【讨论】:

  • @πάνταῥεῖ 应该就是这样(返回值的函数 - 不是本地的)
  • 啊抱歉,我误解了你的示例,我认为它应该简单地演示 A 的堆栈分配(这将是一个很好的提及)。
  • 你应该保留我的其他编辑,关于源代码表示。
  • @πάνταῥεῖ 口味问题(这样更干净,不引用任何代码)
  • 如果你显示代码,你应该这样渲染它(因为它提高了可读性。至少对我来说),但是,也许是品味问题。
【解决方案2】:

您不需要将新的 A() 分配给 b,因为通过调用 b = dum(),您已经使 b 指向与 a 相同的内存位置。请记住,通过使用指针,您不会将内容分配给 b,您只需分配内存位置地址。

实际上,如果你先做b = new A(),然后再做b = dum(),你会失去对b指向的内存位置的引用,这会导致内存泄漏。

【讨论】:

    【解决方案3】:

    你的两个例子都是合法的。正如其他人已经建议的那样,有更好的方法,但原则上你的代码很好。我试图添加一些 cmets 来解释发生了什么。希望澄清一下。

    并且“不 - 你不需要为 b 保留内存”。编译器会为你处理。

    你的第一个例子

    A* dum()
    {
        A* a;               // The compiler reserves memory for holding
                            // the pointer a on the stack. 
    
        a = new A();        // On run time you reserve memory on the heap
                            // for holding an instance of class A.
    
        doSomethingOnA(a);  // Some function call where you pass the pointer
    
        return a;           // Return the pointer. This will also release
                            // the stack memory used for holding the pointer a.
    }
    

    在另一个函数中:

    void func()
    {
        A* b;               // The compiler reserves memory for holding
                            // the pointer b on the stack. 
    
        b = dum();          // The value of the pointer b is changed
                            // so it points to the instance of class A
                            // which is in the heap. The pointer b is
                            // still on the stack.
    
        // ... more code
    
        delete b;           // Delete b to free the heap memory 
                            // (and call the class A destructor).
    
        return;             // This will release
                            // the stack memory used for holding the pointer b.
    }
    

    你的第二个例子

    原理是一样的。

    而且“不——你不需要函数 dum(..) 中的 new。 事实上,这将是一个错误。

    bool dum(A* a)
    {
      // As this function has no local variable, no stack
      // memory will be needed for holding variables.
    
      // A* a = new A() -- Is this needed?     NO - it would be a bug
    
      doSomethingOnA(a);
    
      return 1;
    }
    
    
    void func()
    {
        A* b;               // The compiler reserves memory for holding
                            // the pointer b on the stack. 
    
        b = new A();        // On run time you reserve memory on the heap
                            // for holding an instance of class A.
                            // The value of the pointer b is changed
                            // so it points to the instance of class A
                            // which is in the heap. The pointer b is
                            // still on the stack.
    
        dum(b);             // Just a function call
    
        // ... more code
    
        delete b;           // Delete b to free the heap memory 
                            // (and call the class A destructor).
    
        return;             // This will release
                            // the stack memory used for holding the pointer b.
    }
    

    注意: 编译器可能会优化堆栈的使用,以便函数内的局部变量完全保存在寄存器中,因此根本不需要任何内存。

    【讨论】:

      猜你喜欢
      • 2012-03-23
      • 1970-01-01
      • 1970-01-01
      • 2014-10-25
      • 1970-01-01
      • 2010-12-11
      • 2010-11-07
      • 2022-01-21
      相关资源
      最近更新 更多