C++在堆和栈上分配内存?

8

作为来自Java背景的开发者,我仍然对于C++中的内存分配有些困惑。我非常肯定前两个语句是正确的:

void method() {
    Foo foo;    // allocates foo on the stack, and the memory is freed
                // when the method exits
}

void method2() {
    Foo *foo = new Foo();   // allocates foo on the heap
    delete foo;             // frees the memory used by foo
}

但是像这样的东西呢?
void method3() {
    Foo foo = *new Foo();   // allocates foo on the heap, and then copies it to the stack?
                            // when the method exits, the stack memory is freed, but the heap memory isn't?
}

如果我在method3()中将foo添加到全局数组中,那么如果我在方法退出后尝试访问foo的其中一个数据成员,是否有效?method3()是否容易发生内存泄漏?
提前感谢。

2
Foo foo(); 实际上并不分配任何东西,它只是声明了一个函数。 - chris
1个回答

10
Foo foo(); 

声明一个名为foo的函数,该函数返回一个Foo对象并且不需要任何参数。这在C++中被称为最令人困惑的解析方式。你可能意味着:

Foo foo; 

它在本地/自动存储中创建一个名为foo的对象。一旦声明该对象的作用域{ }结束,该对象将自动释放。
Foo *foo = new Foo();   // allocates foo on the heap
delete foo;

这是真的,一旦你调用 delete,指向堆上的对象 foo 就被释放了。没有内存泄漏。


 Foo foo = *new Foo(); 

在堆上分配一个Foo对象,然后使用该对象的副本初始化foo。由于您没有指向堆分配对象的指针,这将导致内存泄漏。请注意,如果Foo的析构函数有一些会导致副作用的代码,则不仅仅是内存泄漏,而是未定义的行为。

1
@nebulabrot:Foo foo; 可以实现这个功能,而不是 Foo foo(); - Alok Save
1
@Alok Save:仅仅说“标准就是这么规定的”是最没有帮助的回答。哪一行标准规定了这个呢?你确定对于每一个Foo的定义都会遇到这个标准问题吗? - CygnusX1
1
我通过访问https://dev59.com/hmLVa4cB1Zd3GeqPtBYy来回答了这个问题。 - CygnusX1
1
我完全可以省略“场景数量”的声明,仍然可以就标准的哪个元素导致了未定义的行为提出一个完全有效的问题。遗憾的是你没有被迫回答它,但我自己找到了答案 :) 至于具体的场景示例:如果Foo的构造函数具有在某个全局创建对象集合中注册自己的副作用(析构函数 - 注销),上述代码将完全正常。这种简单的管理将防止上述示例中的任何Foo内存泄漏。另一个例子可能包括Foo的重载new运算符... - CygnusX1
@AlokSave:谢谢先生。当我这样写时,有没有办法防止内存泄漏呢?Foo f=*new Foo(); - Destructor
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接