問題の説明:
$ C $ジェネリック$ベクトル$を実装するために平易な言葉を使って、コピーコンストラクタとモバイル構成をサポートしています。
デザイン:
要素の現在の数と現在で開か保存スペースの私たちは、ポインタ・メモリ・ブロックを保存$ベクトル$適用、加えて、我々は2つの$のサイズを取る$ _ $ T $のタイプがありましたので、$ベクタ$は、動的配列であります。それは私たちが次のように定義する$ベクトル$構造を必要とします:
構造体のベクトル { T * BUF。 size_tのサイズ、容量; }。
私たちのデザインは、占有メモリ変数の要素は、メモリブロックのサイズは二つの選択肢と考えることができないので、一般的なので、$ベクトル$、$ T $の型の変数であるため。
1. $ $ $構造ベクトル$ $要素に増加$ _ $サイズ$、$メモリブロックのサイズと、アプリケーション時間を自動的に計算することができる受信ベクトル$要素を作成します。
ポインタのサイズが固定されているので、子供の必要性を完全に、要素の大きさを考慮していないので、その要素に直接2. $ $ $のボイド* $ポイント、。
第1の実施形態は単純であるが、全体$ $ベクトルをコピーする必要があり、素子構造であり、それはポインタ(左下)が含まれている場合、同じデータの同じ位置を指す2つの$ $ベクトル要素が存在することになりますブロック(右下)。
前にコピーします。
コピーした後:
あなたは$ダット$ $ベクトル別で$、その後、別の$別の$ベクトル$でアクセスDAT $を変更する場合は間違っている可能性があります。一方、そのようなデータは、手動でコピーまたは伝送パラメータ、$ $あまりにも面倒を一back。デストラクタは、手動変速機パラメータを必要とする、比較的面倒であると同時に。保存は、多くのスペースが無駄になるような各構造体にコンストラクタとデストラクタをコピーします。
改善:保存$ $ベクター構造体でコンストラクタとデストラクタグループ要素をコピーして、このソリューションを使用します。
すばらしいです!あなたは盲目の学生の中国のポイントを見つけます。あなたが構築して達成することができません。このような動きで驚かれることでしょう。
第2の方式は、$ void *型の$を使用し、次に、このデータ要素を指します。しかし、この方法は、構造体へのポインタを持っている、そのような問題が残っている、我々は、上記のアイデアの開発を参照し、プラス要素スペース、コピーコンストラクタとデストラクタ、この問題が解決され、およびモバイル設定のための時間直接データ要素のポインタのベクトル$ $特定の場所に割り当てられています。
スナップ!それは完璧に見えます。
その後、我々はそれを実現するために始めました:
以上$ベクトル醜い$へのコピーコンストラクタとデストラクタバルクデータ要素まず、我々はそれをパッケージ化(私の混乱の名前を取ります):
構造体data_arg { size_tのu_size。 void *型(*アサイン)(定数void *型の_src)。 void *型(*破壊)(void *型_dat)。 }。
その後、我々は、上記のオプションIIに従って$ベクトル$構造を設計します。
構造体のベクトル { 無効** bufが。 size_tのサイズ、容量; data_arg dat_arg; }。
その後、我々は、機能を設計し始めました。
(注:$キャッチ$ _ $のexec $は独自の罰金を無視して何を教えてください、私のプロジェクトを扱うライブラリの例外です)
最初は、作成することです:
ベクトル* vec_init(data_arg _dat_arg) { ベクトル* PTR =(ベクトル*)はmalloc(はsizeof(ベクトル))。 * PTR = {(ボイド**)はmalloc(はsizeof(ボイド*)* vec_init_size)、 0、vec_init_size、_dat_arg }。 PTRを返します。 }
比較的単純な、言うことはありません。
次に、関数のコピーコンストラクタとデストラクタの呼び出しデータを実装します:
void *型vec_new_data(ベクトル* _vec、CONST void *型の_dat) { 場合(_vec-> dat_arg.assign!) { void *型DST =のmalloc(_vec-> dat_arg.u_size); memcpy(DST、_dat、_vec-> dat_arg.u_size)。 DST返します。 } 戻り_vec-> dat_arg.assign(_dat)。 } void *型vec_delete_data(ベクトル* _vec、void *型_dat) { 場合(_vec-> dat_arg.destroy!) 無料(_dat)。 他 _vec-> dat_arg.destroy(_dat)。 NULLを返します。 }
注:それはポインタの自由であるならば、私は直接、サブコピーコンストラクタとデストラクタポインタがNULL $ $しているので、こと、少し高い効率をメモリにコピーする構造を設計しました。
そして、コピーコンストラクタ:
void *型vec_assign(のconst void *型_vec) { 場合(_vec!の) catch_exce(6); ベクトルVEC * =(ベクトル*)_ VEC。 ベクトル* newvec = vec_init(vec-> dat_arg)。 vec_resize(newvec、vec->容量) newvec->サイズ= vec->サイズ。 (; I <newvec->サイズ++ I iが0 = INT)のため newvec-> BUF [I] = vec-> dat_arg.assign(vec-> BUF [I])。 newvec返します。 }
そしてデストラクタデュオを空にする:
空vec_clear(ベクトル* _vec) { 場合(_vec!) catch_exce(6); (; I <_vec->サイズ++ I iが0 = INT)のため _vec-> BUF [I] = vec_delete_data(_vec、_vec-> BUF [I])。 } ボイド* vec_destroy(ボイド* _vec) { IF(_vec!) catch_exce(6)。 ベクトルVEC * =(ベクトル*)_ VEC。 vec_clear(VEC)。 無料(vec-> BUF); 無料(VEC)。 NULLを返します。 }
そして、機能の残りの部分は、自身が仕事を得るものを実現しています。
容量を確認してください:
空vec_check_capacity(ベクトル* _vec) { 場合(_vec!) catch_exce(6); IF(_vec->サイズ== _vec->容量) vec_resize(_vec、_vec->容量<< 1)。 }
リサイズ:
size_tのvec_resize(ベクトル* _vec、size_tの_size) { IF(_vec!) catch_exce(6)。 無効** TMP =(無効**)のrealloc(_vec-> BUF、はsizeof(void *型)* _size)。 (!TMP)であれば catch_exce(6); _vec-> BUF = TMP、_vec->容量= _size。 >容量_vec-返します。 }
$ $ _ $バック$(コピー)、$押し$ _ $バック$ _ $なし$ _ $ $(運動を)コピーをプッシュ
size_tのvec_push_back(ベクトル* _vec、void *型の_dat) { 場合(_vec!) catch_exce(6); (!_dat)であれば catch_exce(7); vec_check_capacity(_vec)。 _vec-> BUF [_vec->サイズ++] = vec_new_data(_vec、_dat)。 >サイズ_vec-返します。 } size_tのvec_push_back_no_copy(ベクトル* _vec、ボイド* _dat) { IF(_vec!の) catch_exce(6)。 (!_dat)であれば catch_exce(7); vec_check_capacity(_vec)。 _vec-> BUF [_vec->サイズ++] = _dat。 >サイズ_vec-返します。 }
$ポップ$ _ $バック$(デストラクタ)、$ポップ$ _ $バック$ _ $なし$ _ $削除$(ないデストラクタ)
size_tのvec_pop_back(ベクトル* _vec) { IF(_vec!) catch_exce(6)。 _vec-> BUF [--_ vec->サイズ] = vec_delete_data(_vec、_vec-> BUF [_vec->サイズ])。 >サイズ_vec-返します。 } size_tのvec_pop_back_no_delete(ベクトル* _vec) { IF(_vec!) catch_exce(6)。 _vec-> BUF [--_ vec->サイズ] = NULL; >サイズ_vec-返します。 }
注:境界線なしのチェックはありませんが、私は自分自身を追加知らせます。
ありがとうございます!
すべてのソースコードを参照することがここに。これは$ Cパーサーとデザインなので、一般的な$ベクトル$を使用する必要があります$ C $の私自身の純粋な言語の言語のサブセット語彙$です。