0

私はプログラムを書いています.1つのクラスがあり、そのクラスの中に(または外側に、それが問題にならないことを願っています)、私は構造体を持っています. そのクラスでは、構造体要素の配列を作成する必要があります(たとえば、ベクトルを使用できることはわかっていますが、プログラムでは単純な動的配列の使用のみが許可されています)。

配列を として宣言しT * arr[SIZE]ますT。 は構造体です。唯一の問題は、配列の正確なサイズがわからず、必要に応じてサイズを大きくする必要があることです。だから私はそれをサイズ変更する関数を書きました:

if( some cond ){
    T * tmpArr[newSIZE];
    memcpy( tmp, db, newSIZE*sizeof(T));
    delete [] arr;
    arr = tmpArr;
}

しかし、私が推測する式に応答するMyClass::T[....]互換性のないエラーが発生しています。MyClass::T*[SIZE]arr = tmpArr

私が間違っていることを教えてもらえますか?そして、どのように宣言する方が良いですT * arr[size]T * arr = new T[size]、また、その場合、配列のサイズを変更する (そして古いものからメモリを解放する) にはどうすればよいですか?

アップデート:

答えてくれてありがとう、私はそれに応じてプログラムで行いました:

    T * tmp = new T[newSIZE];
    memcpy( tmp, db, newSIZE*sizeof(T) );
    delete [] db;
    db = tmp;

db を削除して割り当てdbた後tmp、 db (または tmp ) に含まれるすべてのデータを出力しようとすると、奇妙なことが起こります。

   Smith2 Michigan ave▒ ACME, Ltd. One ACME roa▒
   Smit▒ Michigan ave` ACME, Ltd. One ACME roa "

   One ACME road#@"▒▒▒▒Michigan ave`▒▒▒▒Smit▒"

   ▒▒ ▒8 Ltd.#Michigan avenuemith4▒aF▒

削除して割り当てる前に同じデータを印刷すると、必要な通常のテキストが得られます。そして、プログラムの後(以前はなかったので、おそらくそれが私のコードに問題があるため、 Segmentation fault が発生します)。ところで、私は Windows でstructofstd::stringと cygwin を使用しています。ここで何が問題なのか分かりますか?

4

5 に答える 5

4

T* tmpArr[newSIZE];へのポインターの可変長配列をT宣言します。可変長配列は標準 C++ の一部ではないことに注意してください (これらは C99 の一部ですが、C++ では GCC の拡張としてのみ使用できます... したがって、このコードは異なるコンパイラではコンパイルできません)。

完全に合理的な解決策は を使用することstd::vectorですが、あなた自身がそれを使用することは許可されていないと書いているので、これがあなたができることです。

  1. T* tmpArr[newSIZE];に変更T* arr = new T[size];
  2. この配列のサイズを変更するには:
    1. 新しい配列を割り当てます:T* newArr = new T[newSize]
    2. 古い配列から要素をコピーします:memcpy(newArr, arr, size * sizeof(T))
    3. を使用して古い配列の割り当てを解除しますdelete[]delete[] arr
    4. ポインター自体を変更しdeleteないため、手順 3 の後に無効な (ぶら下がっている) ポインターがあるため、新しい配列の最初の要素へのポインターを古い配列に割り当てます。arr = newArr
  3. 使用している配列のサイズを追跡します

型のオブジェクトT* arr = new T[size]を保持するのに十分な大きさのメモリを割り当て、の既定のコンストラクタを使用してこれらのオブジェクトを構築することに注意してください。最初の要素のアドレスは、これらの要素が存在する連続したメモリ ブロックを指すように割り当てられます。sizeTTarr

于 2013-03-25T19:50:39.343 に答える
3
T arr[N];

この形式の宣言により、サイズの配列Nと自動保存期間が得られます。これは修正されました。この配列のサイズは変更できません。サイズNはコンパイル時の定数でなければなりません。

T* arr = new T[N];

この宣言は、T*自動保存期間を持つ を定義します。ただし、動的ストレージ期間Nを持つサイズの配列も作成します。ここで、サイズはコンパイル時の定数である必要はありません。N

ただし、これは役に立ちません。動的配列のサイズを変更することはできません。delete[] arr古い配列を破棄してから、new T[NewSize]どうにかしてデータをコピーする必要があります。

これは確実に面倒になり、実際にそうです。あなたのコードでは、2 つの異なるタイプの割り当てを混同しています。delete[] arr動的保存期間がありarrませんが、実行しようとしています。あなたは単にこれを行うことはできません. のように、ある配列を別の配列に割り当てることもできませんarr = tmpArr;

代わりに、C++ 標準ライブラリは、コンテナーと呼ばれる多くの型を提供します。これらにより、動的にサイズ変更可能な一連の要素を非常に簡単に作成できます。たとえば、std::vector<T>.

std::vector<T> arr;

Astd::vectorは要素なしで始まります。を実行するだけで要素を追加できますarr.push_back(value)。を実行することで、非常に簡単にベクターのサイズを一度に変更することもできますarr.resize(newSize)

于 2013-03-25T19:41:14.817 に答える
1

次のように作成した配列を削除しようとしていると思います。

T array[size];

ただし、これに対して delete を呼び出すべきではありません。この配列は、範囲外になると削除されます。配列を作成して後で解放したい場合は、new配列を宣言するときに演算子を使用する必要があります。解放したい場合は を使用してdeleteください。

std::vectorとにかく、自分でやろうとするのではなく、使いたいと思うかもしれません。このことについて学ぶことに興味がある場合は、Microsoft のチャネル 9 に Stephen T. Lavavej によるビデオ シリーズがありました。

http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-/C9-Lectures-Introduction-to-STL-with-Stephan-T-Lavavejこれは本物の宝石。

于 2013-03-25T19:40:58.567 に答える
0

簡単な解決策は、四角い車輪を再発明するのではなくstd::vector<Type>、標準ライブラリーにある既に丸く洗練されたテンプレートを使用することです。

于 2013-03-25T19:41:45.487 に答える
0

実際に へのポインタを格納したいとしますT。必要がある:

  • *へのポインターの配列を割り当てているため、不足している を追加しますT
  • のサイズを削除しtmpArrarr

そう:

// arr definition
 T **arr;;

// arr resizing code
if( some cond ){
    T **tmpArr;
    memcpy( tmp, db, newSIZE*sizeof(T *));
    delete [] arr;
    arr = tmpArr;
}

配列はではなくへのポインターをTT格納し、tmpArrサイズはコンパイル時に不明であるため、その型で指定することはできません。

警告: 新しいサイズが現在のサイズよりも小さい場合、配列の末尾にあるポインターが失われます。その上でテストを追加し、これらの余分なものを削除するT(コンテナーがそれらを所有している場合) か、単に例外をスローする必要があります。これは、コードが配列のサイズを増やすことだけを想定しているためです。

于 2013-03-25T20:10:20.467 に答える