関数内の配列にメモリを動的に割り当てています。私の質問は次のとおりです。関数の実行が終了すると、メモリは解放されますか?
コード:
void f(){
cv::Mat* arr = new cv::Mat[1];
...
}
関数内の配列にメモリを動的に割り当てています。私の質問は次のとおりです。関数の実行が終了すると、メモリは解放されますか?
コード:
void f(){
cv::Mat* arr = new cv::Mat[1];
...
}
いいえ、使用して割り当てられたメモリnew
は、ポインターがスコープ外になったときに自動的に解放されません。
ただし、スコープ外になったときにメモリの解放を処理する C++11 の を使用できます (使用する必要があります) 。unique_ptr
void f(){
std::unique_ptr<cv::Mat[]> arr(new cv::Mat[1]);
...
}
C++11 はshared_ptr
、コピーしたいポインターも提供します。最新の C++ は、これらの「スマート ポインター」を使用するよう努めるべきです。これは、パフォーマンスにほとんど影響を与えることなく、より安全なメモリ管理を提供するためです。
いいえそうではありません。呼び出して解放する必要があります
delete[] arr;
ただし、動的に割り当てる必要があるかどうかを自問する必要があります。これには、明示的なメモリ管理は必要ありません。
void f(){
cv::Mat arr[1];
...
}
動的なサイズの配列が必要な場合は、std::vector
. ベクターは内部的に動的に割り当てますが、リソースの割り当て解除を処理します。
void f(){
std::vector<cv::Mat> arr(n); // contains n cv::Mat objects
...
}
いいえ。へのすべての呼び出しは、どこか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
あることを確認する必要があることです。これは、さまざまな方法で実現できます。 vector
N
N-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;
いいえ、もちろん違います。
正確に1new
つ必要ですdelete
。
正確に1new[]
つ必要ですdelete[]
。
一致する がないためdelete[]
、プログラムが壊れています。
(そのため、C++ を使用する大人の方法は、new
or ポインターをまったく使用しないことです。そうすれば、これらの問題は発生しません。)
いいえ。ヒープに割り当てられた配列です。範囲外になる前に削除する必要があります。
void f() {
cv::Mat * arr = new cv::Mat[1];
// ...
delete [] arr;
}