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 iteselfは自動保存期間を持つ変数です。これは、範囲外になるとarr それ自体が破棄されることを意味します。ただし、それは自動保存期間を持たない変数であるためarr、指すものはそうではありません。

それ自体が自動保存期間を持っているという事実arrは、自動オブジェクトが破棄されたときに保存されたポインターを破棄するクラスで生ポインターをラップすることにより、有利に使用できます。このオブジェクトは、 RAIIと呼ばれるイディオンを使用して、いわゆる「スマート ポインター」を実装します。これは適切に設計されたアプリケーションでは非常に一般的な要件であるため、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[]。これを行うには、上で使用したものと非常によく似た構文を使用します。本当の「落とし穴」の 1 つは、 s は動的なサイズであるため、 position に要素を割り当てようとする前に、 に少なくとも要素がvectorあることを確認する必要があることです。これは、さまざまな方法で実現できます。 vectorNN-1

vector最初からwithアイテムを作成できます。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

いいえ、もちろん違います。

正確に1newつ必要ですdelete

正確に1new[]つ必要ですdelete[]

一致する がないためdelete[]、プログラムが壊れています。

(そのため、C++ を使用する大人の方法は、newor ポインターをまったく使用しないことです。そうすれば、これらの問題は発生しません。)

于 2012-11-02T16:08:29.820 に答える
1

いいえ。ヒープに割り当てられた配列です。範囲外になる前に削除する必要があります。

void f() {

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

    // ...

    delete [] arr;

}
于 2012-11-02T16:08:47.647 に答える