2

我正在为函数中的数组动态分配内存。我的问题是:一旦函数完成运行,内存是否被释放?

代码:

void f(){
    cv::Mat* arr = new cv::Mat[1];
    ...
}
4

5 回答 5

6

new不,当指针超出范围时,不会自动释放分配的内存。

但是,您可以(并且应该)使用 C++11 unique_ptr,它在超出范围时处理释放内存:

void f(){
    std::unique_ptr<cv::Mat[]> arr(new cv::Mat[1]);
    ...
}

C++11 还提供shared_ptr了您可能想要复制的指针。现代 C++ 应该努力使用这些“智能指针”,因为它们提供更安全的内存管理,几乎不会影响性能。

于 2012-11-02T16:09:43.853 回答
4

不它不是。你必须通过调用释放它

delete[] arr;

但是你应该问问自己是否有必要动态分配。这将不需要显式的内存管理:

void f(){
    cv::Mat arr[1];
    ...
}

如果需要动态大小的数组,可以使用std::vector. 向量将在内部动态分配,但会负责取消分配它的资源:

void f(){
    std::vector<cv::Mat> arr(n); // contains n cv::Mat objects
    ...
}
于 2012-11-02T16:08:35.923 回答
4

不。每个呼叫都new需要与delete某个地方的呼叫相匹配。

在您的情况下arr ,本身是一个具有自动存储持续时间的变量。这意味着当它超出范围时arr 自身将被销毁。但是指向的东西arr没有,因为是一个没有自动存储持续时间的变量。

arr通过将原始指针包装在一个类中,该类在销毁自动对象时销毁存储的指针,可以利用它本身具有自动存储持续时间这一事实。该对象利用称为RAII的 idion来实现所谓的“智能指针”。由于这是精心设计的应用程序中非常常见的要求,因此 C++ 标准库提供了许多您可以使用的智能指针类。在 C++03 中,您可以使用

std::auto_ptr

在 C++11auto_ptr中已弃用并被其他几个更好的智能指针取代。其中:

std::unique_ptr std::shared_ptr

一般来说,使用智能指针代替原始(“哑”)指针是一个好主意,就像您在此处所做的那样。

如果您最终需要的是 C99 支持的动态大小的数组,那么您应该知道 C++ 没有直接支持它们。一些编译器(尤其是 GCC)确实支持动态大小的数组,但这些是特定于编译器的语言扩展。为了在仅使用可移植的、符合标准的代码时获得近似动态大小的数组,为什么不使用std::vector?

编辑: 分配给数组:

在您的评论中,您描述了分配给该数组的方式,我认为这是这样的:

int* arr = new int[5];
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;

如果是这种情况,您可以vector通过调用来完成相同的操作vector::operator[]。这样做看起来使用与您在上面使用的非常相似的语法。一个真正的“陷阱”是,由于s 是动态大小的,因此在尝试将元素分配到 position 之前vector,您需要确保 svector至少具有元素。这可以通过多种方式实现。 NN-1

您可以从一开始就创建vector带有N项目的项目,在这种情况下,每个项目都将被初始化:

vector<int> arr(5); // creates a vector with 5 elements, all initialized to zero
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;

您可以resize事后的向量:

vector<int> arr; // creates an empty vector
arr.resize(5); // ensures the vector has exactly 5 elements
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;

或者,您可以使用各种算法来用元素填充向量。一个这样的例子是fill_n

vector<int> arr; // creates empty vector
fill_n(back_inserter(arr), 5, 0);  // fills the vector with 5 elements, each one has a value of zero
arr[1] = 1;
arr[4] = 2;
arr[0] = 3;
于 2012-11-02T16:14:12.563 回答
1

不,当然不。

对于new您需要的每一个delete.

对于new[]您需要的每一个delete[].

由于您没有匹配项delete[],因此您的程序已损坏。

(出于这个原因,使用 C++ 的成人方式是根本不使用new或指针。那么你就不会有这些问题。)

于 2012-11-02T16:08:29.820 回答
1

不。在堆上分配的数组,你必须在它超出范围之前删除它:

void f() {

    cv::Mat * arr = new cv::Mat[1];

    // ...

    delete [] arr;

}
于 2012-11-02T16:08:47.647 回答