C++およびベクトル/リストの前日では、データをもっと格納する必要があるときに、配列のサイズをどのように拡大しましたか?ベクトルをcで複製する方法は?
答えて
典型的なCのコードは次のようになりますのreallocが失敗した場合、それはゼロを返しますが、古い記憶がまだ有効であることを
void* newMem = realloc(oldMem, newSize);
if(!newMem)
{
// handle error
}
oldMem = newMem;
注、この典型的な使い方は、メモリリークが発生します。残念ながら
oldMem = realloc(oldMem, newSize);
if(!oldMem)
{
// handle error
}
それは非常に一般的です。
また、C++のvector/listには特別なことはありません。同様の構造体をC言語で実装することができます。構文(およびエラー処理)は異なって見えます。たとえば、Cのstd :: vectorのLodePNG'sアナログを参照してください。
多くのCプロジェクトでは、ベクターのようなAPIが実装されています。ダイナミックアレイはそのような共通のニーズであり、可能な限りメモリ管理を抽象化するのが良いことです。その後、彼らはvector
で動作するさまざまなAPI関数呼び出しを持っているでしょう
typedef struct dynamic_array_struct
{
int* data;
size_t capacity; /* total capacity */
size_t size; /* number of elements in vector */
} vector;
:典型的なCの実装は次のようになります
int vector_init(vector* v, size_t init_capacity)
{
v->data = malloc(init_capacity * sizeof(int));
if (!v->data) return -1;
v->size = 0;
v->capacity = init_capacity;
return 0; /* success */
}
その後、もちろん、あなたがpush_back
、insert
、resize
のための機能を必要とします、size
がcapacity
を超えた場合はrealloc
となります。再割り当てが必要な場合
vector_resize(vector* v, size_t new_size);
vector_push_back(vector* v, int element);
通常、capacity
はすべての時間を再割り当てを避けるために倍増しています。これは通常std::vector
で内部的に採用されているものと同じですが、通常std::vector
はC++オブジェクトの構築/破壊のためにrealloc
を呼び出さない点が異なります。むしろ、std::vector
は、新しいバッファを割り当て、次にコンストラクト/ムーブを(バッファnew
を使用して)新しいバッファにコピーします。
Cの実際のベクトル実装では、int
ではなくvoid*
ポインターを要素として使用することがあるため、コードはより一般的です。とにかく、このようなことは多くのCプロジェクトで実装されています。 Cのベクトル実装の例については、http://codingrecipes.com/implementation-of-a-vector-data-structure-in-cを参照してください。
ここでは、構造体のデータ変数のポインタを作成するようですが、他の多くの場合は私は、構造のデータ変数がダブルポインタによって保持されていることを見た。これら2つの方法の違いは何ですか? – Kai
リンクが壊れています(https://gist.github.com/EmilHernvall/953968/0fef1b1f826a8c3d8cfb74b2915f17d2944ec1d0を参照してください)普及している実装のようです。 –
実装に必要なメンバーを保持する構造体を隠すことから始めます。次に、構造の内容を操作する関数のグループを提供します。このような
何か:これにさらに
typedef struct vec
{
unsigned char* _mem;
unsigned long _elems;
unsigned long _elemsize;
unsigned long _capelems;
unsigned long _reserve;
};
vec* vec_new(unsigned long elemsize)
{
vec* pvec = (vec*)malloc(sizeof(vec));
pvec->_reserve = 10;
pvec->_capelems = pvec->_reserve;
pvec->_elemsize = elemsize;
pvec->_elems = 0;
pvec->_mem = (unsigned char*)malloc(pvec->_capelems * pvec->_elemsize);
return pvec;
}
void vec_delete(vec* pvec)
{
free(pvec->_mem);
free(pvec);
}
void vec_grow(vec* pvec)
{
unsigned char* mem = (unsigned char*)malloc((pvec->_capelems + pvec->_reserve) * pvec->_elemsize);
memcpy(mem, pvec->_mem, pvec->_elems * pvec->_elemsize);
free(pvec->_mem);
pvec->_mem = mem;
pvec->_capelems += pvec->_reserve;
}
void vec_push_back(vec* pvec, void* data, unsigned long elemsize)
{
assert(elemsize == pvec->_elemsize);
if (pvec->_elems == pvec->_capelems) {
vec_grow(pvec);
}
memcpy(pvec->_mem + (pvec->_elems * pvec->_elemsize), (unsigned char*)data, pvec->_elemsize);
pvec->_elems++;
}
unsigned long vec_length(vec* pvec)
{
return pvec->_elems;
}
void* vec_get(vec* pvec, unsigned long index)
{
assert(index < pvec->_elems);
return (void*)(pvec->_mem + (index * pvec->_elemsize));
}
void vec_copy_item(vec* pvec, void* dest, unsigned long index)
{
memcpy(dest, vec_get(pvec, index), pvec->_elemsize);
}
void playwithvec()
{
vec* pvec = vec_new(sizeof(int));
for (int val = 0; val < 1000; val += 10) {
vec_push_back(pvec, &val, sizeof(val));
}
for (unsigned long index = (int)vec_length(pvec) - 1; (int)index >= 0; index--) {
int val;
vec_copy_item(pvec, &val, index);
printf("vec(%d) = %d\n", index, val);
}
vec_delete(pvec);
}
彼らは機能グループのVEC *の代わりに、ボイド*を使用してカプセル化を達成し、実際に中にそれを定義することによって、ユーザからの構造定義を非表示にしますCモジュールにはヘッダーではなく機能のグループが含まれています。また、ヘッダーから外してCモジュールでのみプロトタイプを作成することで、非公開であると考える機能を隠すことになります。
struct vc_vector {
size_t count;
size_t element_size;
size_t reserved_size;
char* data;
vc_vector_deleter* deleter;
};
...
vc_vector* vc_vector_create_copy(const vc_vector* vector) {
vc_vector* new_vector = vc_vector_create(vector->reserved_size/vector->count,
vector->element_size,
vector->deleter);
if (unlikely(!new_vector)) {
return new_vector;
}
if (memcpy(vector->data,
new_vector->data,
new_vector->element_size * vector->count) == NULL) {
vc_vector_release(new_vector);
new_vector = NULL;
return new_vector;
}
new_vector->count = vector->count;
return new_vector;
}
それを使用するには::
これは30分で書かれていますが、保証はありません。 –
あなたは、実装vc_vectorが見ることができる
vc_vector* v1 = vc_vector_create(0, sizeof(int), NULL);
for (int i = 0; i < 10; ++i) {
vc_vector_push_back(v1, &i);
}
// v1 = 0 1 2 3 4 5 6 7 8 9
vc_vector* v2 = vc_vector_create_copy(v1);
// v2 = 0 1 2 3 4 5 6 7 8 9 (copy of v1)
// to get pointer to int:
const int* v2_data = vc_vector_data(v1);
- 1. ベクトルでデータフレームを複製する方法は?
- 2. Python:複製しないで複製リストを複製する方法
- 3. ベクトルで重複を削除する方法(ソートせずに)C++
- 4. GDI + C++でソリッドブラシを複製する方法
- 5. C++で2Dベクトルを返す方法は?
- 6. Oracleインスタンスを複製する方法は?
- 7. Python、Seaborn:corrplotを複製する方法は?
- 8. アイテム/レコードを複製する方法は?
- 9. Microsoft AzureでLinux-VMを複製/複製する方法はありますか?
- 10. Oracleでユーザーを複製する方法
- 11. XCode4でプロジェクトターゲットを複製する方法
- 12. ベクトルで重複を数える方法(C++)
- 13. Grails:行インスタンスをコピー/複製/複製する方法
- 14. MySQLでFULL JOINを複数回複製する方法は?
- 15. C#ステートメントを複製する?
- 16. 3要素のベクトルをC++のベクトルにプッシュバックする方法は?
- 17. OPENCV C++でベクトルのベクトルに要素を格納する方法
- 18. 二重リンクリストを再帰的に複製する方法C++
- 19. C#WinFormのドロップダウンラベルと値を複製する方法
- 20. ジオードで非文字列データを複製アダプタで複製する方法
- 21. Cマクロを複製するには?
- 22. Cでレコードを複製する#
- 23. jQuery DIVを複製する方法「スライドイン」
- 24. pandas datetimeオブジェクトを複製する方法
- 25. ImageAdとResponsiveDisplayAdを複製する方法
- 26. javascript ES6クラスインスタンスを複製する方法
- 27. 値を複製する方法
- 28. postgreSQLの:行を複製する方法
- 29. SWIG:複素数のベクトルをC++からPythonに渡す方法
- 30. SOAP-UIで複合POSTを複製する方法
クールすごい、C++と同等いただきましたので?例えばmalloc = new、free = delete、realloc =? – Kaije
@user:あなたと同等のものが間違っています。それらは次のとおりです:malloc = vector :: vector、free = vector :: clear、realloc = vector :: resize。 – ybungalobill
@ybungalobill、um ... 'vector :: clear()'は実際には 'free'に類似していません。 –