1

C++ でポインターを持っている場合、たとえばint* array;、次のように配列にメモリを割り当てます。

array=new int[10];

次に、配列の 10 個の要素すべてを 0、1、2、3 で初期化します...その後、array=new int[15]; 最初の 10 個の値はまだ残っていますか? 違うと思いますが、間違っていたら訂正してください。

Cには、realloc上記の効果を持つ関数があります。C++ または Java に相当するものはありますか? C++またはJavaで(Vectorクラスを使用せずに、配列を2倍の容量を持つ別の配列に毎回コピーせずに)動的に配列を拡張するにはどうすればよいですか?

4

9 に答える 9

3

new int[X]C++ と Java の両方で where is a integerを実行Xすると、新しく割り当てられた配列への参照が取得されます。

Java では、各エントリがデフォルト値 (プリミティブ データ型の場合は 0、参照データ型の場合は null) を持つように配列が自動的に初期化されます。C++ では、配列は初期化されないため、ガベージが発生します。

もしあなたがそうするなら:

array = new int[10];
array[0] = 0;
array[1] = 1;
// etc
array = new int[15];

2 回目に配列を作成し、それへの参照を variablearrayに入れると、最初の配列への参照が失われます。これは新しい配列であるため、配列を新しく割り当てるための言語の規則に従います。Java では、配列はゼロで埋められたサイズ 15 の配列を指すようになります。C++ では、array はガベージで満たされたサイズ 15 の配列を指します。

Java では、失われた配列は最終的にガベージ コレクションされます。C++ では、メモリ リークが発生しました。

どちらの言語でも、サイズを変更したり、配列を動的に拡張したりすることは禁止されています。新しいものを作成し、古いものから新しいものにすべてをコピーし、古いものを破棄できます。これらの操作を行うメソッドを提供する場合がありますが、既存の配列を拡張することはありません。単に新しい配列を作成し、古い配列から新しい配列にデータをコピーするだけです。

Java にはreallocはなく(ただし、Arrays.copyOf同様に機能する があります)、C++ (および C も同様) では、実際には配列を拡張reallocしません。他の場所により多くのメモリを割り当て、以前に割り当てられたメモリの割り当てを解除し、新しいポインタを返します。既存のポインタを新しいアドレスに置き換える必要があります!

最後に、動的にサイズを変更するコレクション クラスの場合、通常、内部配列があり、その配列がいっぱいになると、クラスはすべてのサイズ変更を内部で行います。つまり、より大きな新しいものを割り当て、要素をコピーし、古いものを破棄します。配列はクラスに完全にカプセル化されているため、上で説明した古い配列への参照について心配する必要はありません。

于 2013-06-26T14:03:24.547 に答える
2

C++ と Java の両方における配列の概念の核心は、固定サイズのコレクションです。reallocこの概念ではある種のバックドアのように見えるかもしれませんが、特定の配列を拡張することを約束するものではありません。別の場所に配列を作成し、元のコンテンツをコピーして元のメモリを解放する可能性があります。そして、おそらくそうなるでしょう。
したがって、可変サイズのコレクションが必要な場合はstd::vector、C++ およびArrayListJava で使用します。または、この機能を自分でコーディングすることもできます。ただし、一度割り当てられたメモリのチャンクを標準のものに拡張することはできないため、独自のメモリアロケータから始める必要があると思います。

于 2013-06-26T14:20:09.650 に答える
1

Java では、メモリ管理は JVM の制御下にあります。それがJavaの美しさです。System.arraycopy() 関数を使用して、配列のコピーを作成できます。目的が配列を拡張することである場合は、宛先配列としてより大きな配列を指定してください。

一方、コレクションを動的に拡張するには、コレクション フレームワークを使用できます。

于 2013-06-26T14:04:46.377 に答える
1

最初の最初の 10 個の値はまだ残っていますか?

C++ では、どこかに がありますが、それらへのハンドルを失いました。アクセスできなくなります。これにより、メモリ リークが発生します。

int* array=new int[10]; // array points to dynamically allocated array
array=new int[15]; // array points to a completely different place now

上記の例では、arrayポインタは、最初に動的に割り当てられた配列にある唯一のハンドルです。他の場所を指すようにすると、配列がリークします。

C++ では、配列の要素がゼロ初期化されていないことにも注意してください。そのためには、配列の値を初期化する必要があります。

int* array=new int[10]();
//                    ^^
于 2013-06-26T14:02:07.220 に答える
0

Javaで配列を動的に拡張するにはどうすればよいですか(Vectorクラスを使用せずに、配列を2倍の容量を持つ別の配列に毎回コピーせずに)?

ではjava.util.Arrays、使用する方法がたくさんあります。あなたの状況では、あなたが必要とするcopyOf

API ドキュメント

array = Arrays.copyOf(array, 15);
于 2013-06-26T14:08:27.937 に答える
0

Java では、配列を動的に拡張することはできません。ArrayList のように、さまざまなデータ構造があります。

Java では、サイズ 10 の最初の配列への参照が残っていない場合、GarbageCollector によって収集されます。

于 2013-06-26T14:01:38.650 に答える
0

C++ での最良のオプションは stl であり、std::vector<int>なぜそれを使用できないのかわかりませんが、使用できないとしましょう。おそらく最良の方法:

const int c_startSize = 10;
const int c_increasing = 13;   //1.3

int * array;
int arraySize = c_startSize;
array = new int[arraySize];
//some code
//now we need to increase size of array.
int * tmp;
tmp = new int[arraySize * c_increasing / 10];
for (int i = 0; i < arraySize; i++)
    tmp[i] = array[i];
arraySize = arraySize * c_increasing / 10;
delete [] array;
array = tmp;
//some code

それがおそらく唯一の方法です。もちろん、reallocまたはmemcpyを使用して値をコピーすることもできますが、これは void ポインターに基づいており、通常、初心者にとってはよりトリッキーです。これが役に立てば幸いです。このためのクラスまたは構造体を作成することを忘れないでください。そうしないと、混乱が大きくなります。

編集:言い忘れましたが、私の答えにはC++のみが含まれ、JAVAは含まれていません。

于 2013-06-26T14:15:02.003 に答える
0

はい、標準 C++ である C++ に相当するものがあります。

std::vector<int> array(10);

その後

array.resize(15);

vector、期待どおりにストレージ メモリを管理します。はvector、C の再割り当て配列ポインターを置き換えるように設計されています。オンスタック配列を置き換えるにはstd::array、C++11 以降があります。オンスタック VLA を置き換えるにはstd::dynarray、C++14 または C++17 を使用します。

誘惑されないでください、realloc時々そのデータをコピーします。(再割り当てされたバッファを取得するのに十分なスペースがインプレースで見つからない場合)

for C++ に相当するものについてはrealloc、いいえ、 にrenew対応する方法newがありません。そして、それは言語に欠けているものではありません。それはクラスで対処されています。メモリ自体を管理し、効率的であり、いや、それを使用するのは不純なスタイルではありません。サイズを変更できる配列を持つことは、C++ の標準的な方法です。reallocmallocstd::vector

于 2013-06-26T14:13:25.093 に答える
0

C++ では、new は常にポインタを返します。配列の名前は配列の最初の要素へのポインタであるため、次のようになります。

 int *array;           //get a point of type int
 array=new int[10];    //allocate 10 ints, and set the array ponter to the first one

 array = new int[15]   //allocate 15 ints, and set the array pointer to the first one

問題は、最初の 10 個の int がメモリ内のどこにあるかを知る方法がないことです。オペレーティングシステムは、私たちが要求したb / cでそれを使用していると「考えます」。しかし、どこにあるのかわからないので使用できません。


今何か役立つもののために。ベクトルを使用します。ベクトルは、動的メモリ割り当てが組み込まれた C++ のオブジェクトであるため、自分で手動で行う必要はありません。

実際にどのように行われるかを確認したい場合は、メモリ割り当てを処理するオブジェクトを自分で作成できます。

于 2013-06-26T14:06:54.020 に答える