C ++での静的配列と動的配列


91

C ++の静的配列と動的配列の違いは何ですか?

クラスの割り当てを行う必要がありますが、静的配列は使用せず、動的配列のみを使用するように指示されています。私は本とオンラインを調べましたが、理解していないようです。

静的はコンパイル時に作成され、動的は実行時に作成されると思いましたが、これをメモリ割り当てと間違えている可能性があります。

C ++の静的配列と動的配列の違いを説明できますか?


1
静的は動的の反対ではありません。あなたが使っている本がひどいものであるか、文脈から外れているのです。うまくいけばこれを解決するために、以下に新しい答えを追加します。
Joshua Clayton

3
この質問の図を参照してください:stackoverflow.com/a/11698458/1143274静的配列はスタックまたはヒープに割り当てられていません。
Evgeni Sergeev

ダイナミックアレイVS *固定アレイ
csguy

回答:


102

ローカル配列はスタック上に作成され、自動保存期間があります。メモリを手動で管理する必要はありませんが、使用している機能が終了すると破棄されます。それらは必然的に固定サイズになります:

int foo[10];

で作成された配列にoperator new[]は動的な保存期間があり、ヒープ(技術的には「フリーストア」)に保存されます。それらは任意のサイズにすることができますが、スタックフレームの一部ではないため、自分で割り当てて解放する必要があります。

int* foo = new int[10];
delete[] foo;

18
これは正しいですが、それがどのように機能するかを説明するためだけです。実際のコードではこれを行わず、代わりにstd :: vectorを使用してください。
Eddy Pronk 2010

23
@Eddy:ベクトルが必要かどうかは状況によって異なります
Casebash 2010年

6
@Casebash:どのような状況で配列を好みますか?「配列ではなく、常にベクトルまたは両端キューを使用することをお勧めします。」-ハーブサッター(より例外的なC ++)
Eddy Pronk 2010年

16
@EddyPronkメモリの断片化の理由から、固定配列を一種のプールとして使用する場合があります。すべての場合にヒープが必要なわけではありません。スタックベースの配列を使用することには特別な利点があります。std :: vectorを、一般的なアンチパターンであるゴールデンハンマーとして扱っています。
void.pointer 2011年

4
@EddyPronk:Herb Sutterは動的配列を意味していると確信してint* foo = new int[N]います。動的配列のように、delete自分で作成する必要があるため、例外がある場合は注意が必要です。静的配列にはこれらの問題はありません。
アレクサンダーマラホフ2013

31

staticはCおよびC ++のキーワードであるため、一般的な説明用語ではなく、staticは変数または配列に適用されると非常に具体的な意味を持ちます。混乱を悪化させるために、それは別々の文脈の中で3つの異なる意味を持っています。このため、静的配列は固定または動的のいずれかになります。

説明させてください:

1つ目はC ++固有です。

  • 静的クラスメンバーは、コンストラクターでインスタンス化されない、またはデストラクタで削除されない値です。これは、メンバーを初期化して他の方法で維持する必要があることを意味します。静的メンバーは、nullに初期化され、コンストラクターが最初に呼び出されたときに割り当てられるポインターである可能性があります。(はい、それは静的で動的です)

2つはCから継承されます:

  • 関数内では、静的変数は、関数呼び出し間でメモリ位置が保持される変数です。これは、一度だけ初期化され、関数呼び出し間でその値を保持するという点で静的です(静的を使用すると、関数は再入可能ではなくなり、スレッドセーフではなくなります)

  • 関数の外部で宣言された静的変数は、同じモジュール内からのみアクセスできるグローバル変数です(他の#includeを含むソースコードファイル)

あなたが尋ねるつもりだった質問(私は思う)は、動的配列と固定またはコンパイル時の配列の違いは何ですか?これは簡単な質問です。コンパイル時の配列は(プログラムがコンパイルされるときに)事前に決定され、関数スタックフレームの一部です。これらは、メイン関数が実行される前に割り当てられます。動的配列は、実行時に「new」キーワード(またはCのmallocファミリー)で割り当てられ、そのサイズは事前にわかりません。プログラムの実行が停止するまで、動的割り当ては自動的にクリーンアップされません。


4
+1、あなたの答えは最も正確で正確であり、より多くの票を獲得する必要があります。
Zボソン

new[]演算子を使用して配列のサイズを宣言する場合、実行時までサイズがわからないのはどうしてですか?すなわちint* p = new int[10]
wulfgarpro 2016年

「これらは、メイン関数が実行される前に割り当てられます。」関連するブロックに入る前にスタック変数を割り当てるのはなぜですか?
AlwaysLearning

スタック変数(通常は関数内のローカル変数)には、スタックフレーム内で事前定義されたサイズと位置があり、メイン関数@AlwaysLearningが実行される前にスタック全体が割り当てられます。関数呼び出しを介してスタックフレームに入ると、スタックポインターは更新されますが、新しいスタックフレームはスタック内にあります。これ以上スタックが割り当てられることはありません。実際、変数が大きすぎる(たとえば、巨大な配列)か、同時に開く関数呼び出しが多すぎると、スタックオーバーフローが発生し、このサイトの名前が付けられます。
ジョシュアクレイトン

@JoshuaClaytonこれは正しくないと思います。何回入力されるかわからない場合、再帰関数にスタックフレーム(複数形に注意)を割り当てるにはどうすればよいですか?
AlwaysLearning

11

クラスで使用されているセマンティクスは混乱していると思います。おそらく「静的」が意味するのは単に「一定サイズ」であり、おそらく「動的」が意味するのは「可変サイズ」です。その場合、定数サイズの配列は次のようになります。

int x[10];

「動的」なものは、実行時に基盤となるストレージを増減できるようにするあらゆる種類の構造です。ほとんどの場合、std::vectorC ++標準ライブラリのクラスで十分です。次のように使用します。

std::vector<int> x(10); // this starts with 10 elements, but the vector can be resized.

std::vectoroperator[]定義されているため、配列と同じセマンティクスで使用できます。


1
「動的配列」とは、単に動的に割り当てられた配列(つまり、実行時にサイズを動的に指定できる配列)を意味することはかなり明らかだと思います。のようにnew int[10]
jalf 2010

@jalf:「静的」という用語についてもっと心配していました。一貫性を保つために、「動的配列」を割り当て済みまたは可変サイズの配列と呼ぶことを好みます。
ベンコリンズ

静的配列は自動でスタックに実装することも、グローバルにしてデータセクションに実装することもできるため、良い点です。どちらも静的ですが、内部的にはそれらにアクセスするコードが大きく異なる可能性があります。
Zボソン

9

静的配列にはコンパイル時にメモリが割り当てられ、メモリはスタックに割り当てられます。一方、動的配列には実行時にメモリが割り当てられ、メモリはヒープから割り当てられます。

int arr[] = { 1, 3, 4 }; // static integer array.   
int* arr = new int[3]; // dynamic integer array.

4
グローバル配列は静的配列であり、スタックからではなくデータセクションに実装されます。
Zボソン

8

用語の意味を明確に定義することが重要です。残念ながら、静的配列と動的配列の意味には複数の定義があるようです。

静的変数は、静的メモリ割り当てを使用して定義された変数です。これは、C / C ++に依存しない一般的な概念です。C / C ++では、次のようにグローバル、ファイル、またはローカルスコープで静的変数を作成できます。

int x[10]; //static array with global scope
static int y[10]; //static array with file scope
foo() {
    static int z[10]; //static array with local scope

自動変数は通常、スタックベースのメモリ割り当てを使用して実装されます。自動配列は、次のようにC / C ++で作成できます。

foo() {
    int w[10]; //automatic array

これらの配列、、、x, y, zおよびwに共通しているのは、それぞれのサイズが固定されており、コンパイル時に定義されることです。

自動配列と静的配列の違いを理解することが重要である理由の1つは、静的ストレージは通常、オブジェクトファイルのデータセクション(またはBSSセクション)に実装され、コンパイラは絶対アドレスを使用して配列にアクセスできるためです。これは、スタックベースのストレージでは不可能です。

動的配列が通常意味するのは、サイズ変更可能な配列ではなく、実行時に決定される固定サイズの動的メモリ割り当てを使用して実装される配列です。C ++では、これはnew演算子を使用して行われます。

foo() {
   int *d = new int[n]; //dynamically allocated array with size n     

ただし、以下を使用して、実行時に定義された修正サイズで自動配列を作成することは可能allocaです。

foo() {
    int *s = (int*)alloca(n*sizeof(int))

真の動的配列の場合std::vector、C ++(またはCの可変長配列)のようなものを使用する必要があります。

OPの質問での割り当ての意味は何ですか?求められていたのは静的または自動配列ではなく、new演算子を使用した動的メモリ割り当て、またはたとえばを使用した固定サイズではない配列のいずれかであったことは明らかだと思いますstd::vector


3

この文脈では、サイズが固定されているという意味で静的であることを意味すると思います。std :: vectorを使用します。これにはresize()関数があります。


2

サイズが実行時にユーザーによって設定される疑似動的配列を作成できますが、その後は修正されます。

int size;
cin >> size;
int dynamicArray[size];

標準のC ++の一部ではありません(C99およびgccのコンパイラ拡張として)。
crackmstr 2014年

1

静的配列

  1. 静的配列には、コンパイル時にメモリが割り当てられます。
  2. サイズは固定です。
  3. スタックメモリスペースにあります。
  4. 例えば。:int array [10]; //サイズ10の配列

動的配列:

  1. メモリは実行時に割り当てられます。
  2. サイズは固定されていません。
  3. ヒープメモリスペースにあります。
  4. 例えば。:int * array = new int [10];

0

はい、そうです。静的配列はコンパイル時に作成されますが、動的配列は実行時に作成されます。違いはメモリの場所に関するものですが、静的はスタックに配置され、動的はヒープに作成されます。.net Frameworkの場合のようにガベージコレクターが存在しない限り、ヒープ上に配置されるものはすべてメモリ管理が必要です。存在しない場合、メモリリークのリスクがあります。


0

静的配列:効率。動的な割り当てや割り当て解除は必要ありません。

静的修飾子を含む関数でC、C ++で宣言された配列は静的です。例:static int foo [5];


1
@admdrew、それは本当ですが、質問は決してうまく答えられませんでした。最良の答えはJoshuaClaytonの答えですが、より良い答えはこれだと思いますstackoverflow.com/questions/17775066/…–
Z boson

@Zboson知ってよかった、ありがとう。ヘーと私は、ほぼ1年前にそのコメントをしたことに気づきました。
admdrew 2014年

-3

静的なarraryは、配列の横にある要素を与えることを意味します

動的なarraryは、配列の横にある要素を与えることなく意味します

例:

     char a[10]; //static array
       char a[];  //dynamic array

彼は正しいと言ったと思います。配列する正確な長さの場合は静的配列であり、長さを指定しない場合は動的配列です。しかし、彼は英語の書き方がわからないので、人々はこの答えをマークダウンします。
muhammad tayyab 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.