使用函数分配内存时会发生什么?

时间:2019-05-02 22:01:50

标签: c++ c++11

通过函数返回新分配的变量时,是否会复制并传递一个副本,并且会自动删除原始副本?

我假设没有内存泄漏

#include <iostream>

using namespace std;

int* allocater()
{

    int* x = new int(1);
    return x; 

    // what happens to the memory allocated to x ?
}


int main()
{


int* a = allocater();
int* b = allocater();


cout<<*a<<"  "<<*b;

delete a;
delete b;

// all memory allocated has been deleted?

}

输出符合预期。

5 个答案:

答案 0 :(得分:5)

  

返回新分配的变量时

具有动态存储的对象不是变量。

该函数中有一个变量。它的名称为x。变量x的类型为int*,即它是指向整数的指针。

  

是否制作并通过了副本,并且原件会自动删除?

x是一个自动变量,因此当它超出范围时会被自动销毁。确实将变量作为返回值复制到调用表达式中-尽管,如果编译器执行命名返回值优化,则有可能删除该副本。如果类型较大或复制速度较慢(指针没有复制),则很有用。

具有动态存储(程序中类型为int)的对象不会自动销毁。必须使用delete表达式释放它们。

答案 1 :(得分:1)

每当这样分配内存时,它就会保留在“堆”上。这是操作系统分配给程序的内存区域。通过使用C ++中的分配函数,例如:new()malloc()(还有其他),该堆的连续块被保留,其地址(指针)返回到堆。调用代码。

在您的函数中:

int *allocater()
{
    int *x = new int(1);
    return x; 
}

保留单个整数大小的内存(可能为4-8字节),并返回该内存的地址。该地址只是一个数字,当将该数字解释为内存中的某个位置时,它称为指针-但它仍然只是一个数字。

因此,当函数返回时,内存仍然分配在堆上。如果您的程序忘记了该数字,则该内存将“泄漏”-您的程序无法使用delete()delete[]()free()对其进行取消分配,因为您没有该数字来告知取消分配功能可在何处释放。

在您的代码中,因为您存储了allocater()的返回值,所以可以使用delete来取消分配该块。因此,您的代码可以正常工作,并且可以正确地取消分配内存。

答案 2 :(得分:0)

在释放它之前什么都不会发生。是的,这是有效的代码,没有泄漏。

在C ++ 11(或更早的auto_ptr-s中)引入了RAII指针:unique_ptrshared_ptr等。因此,如果使用它们:

int* allocater()
{
    auto x = std::make_unique<int>(5);
    return x.get();  // getting raw ptr
}

它变得无效,因为delete被销毁时x被调用,而退出allocater时会发生这种情况。

答案 3 :(得分:0)

C ++没有垃圾收集器。创建本地对象时,将在堆栈上分配内存,并且当它们超出范围时,编译器会自动调用析构函数(取决于对象是否平凡),并在返回后释放内存。

但是,有时您需要动态分配内存。在这种情况下,我们可以使用newdelete显式分配和删除内存。但是,从C ++ 11开始,引入了智能指针,它们只是原始指针的包装。这有助于管理对象的寿命。

原始指针的问题在于,当对象不再有用时,程序员必须明确销毁该对象。

但是,智能指针会自动照顾这一点。

因此,在您的代码中,x是一个局部变量,函数将立即返回。 x被销毁,但它指向的内存未被销毁。

答案 4 :(得分:-1)

非常感谢您的翔实回答和反馈,确实有助于澄清问题, 使用指针就像传递包裹的游戏!

,只要分配的内存有指向它的指针-它可以是 删除而没有泄漏,无论是从函数返回还是在主函数中返回

非常感谢