11

以前の質問で、ポインターの型キャストについて尋ねましたが、malloc の代わりに C++ 割り当てシステムを使用するというより良い解決策に向けられました。(一部の C コードを C++ に変換しています)

ただし、同様の機能にはまだ問題があります。

私が変更され:

tmp = malloc(sizeof(char*) * mtmp); --> tmp = new char*[mtmp];

free(tmp) --> delete [] tmp;

ただし、次の関数で realloc を使用するにはどうすればよいですか。

char* space_getRndPlanet (void)
{
   int i,j;
   char **tmp;
   int ntmp;
   int mtmp;
   char *res;

   ntmp = 0;
   mtmp = CHUNK_SIZE;
   //tmp = malloc(sizeof(char*) * mtmp); <-- replaced with line below
   tmp = new char*[mtmp];
   for (i=0; i<systems_nstack; i++)
      for (j=0; j<systems_stack[i].nplanets; j++) {
         if(systems_stack[i].planets[j]->real == ASSET_REAL) {
            ntmp++;
            if (ntmp > mtmp) { /* need more space */
               mtmp += CHUNK_SIZE;
               tmp = realloc(tmp, sizeof(char*) * mtmp); <--- Realloc
            }
            tmp[ntmp-1] = systems_stack[i].planets[j]->name;

次のエラーが表示されます。

error: invalid conversion from 'void*' to 'char**'|

編集2:

さて、私が得ているコンセンサスは、現在のソリューションを捨てる必要があるということです (私はそれを行うことにオープンです)。

私が正しく理解していることを確認するために、オブジェクトへのポインターの配列の代わりに、オブジェクト自体を含むベクトルが必要なのですか?

4

8 に答える 8

15

C ではvoid*、任意のポインターに暗黙的に変換できます。C++ はそうではないため、 を使用している場合はrealloc、結果を適切な型にキャストする必要があります。

しかし、もっと重要なことは、realloc返されたポインターでの使用new[]は未定義の動作です。また、に相当する直接的な C++ スタイルはありませんrealloc

あなたの選択は、少なくとも最も慣用的なものから次のとおりです。

  • malloc/ realloc/に固執しfree、ポインターをキャストします。
  • の代わりにnew[]+を使用delete[]realloc
  • std::vector<std::string>自分のメモリを管理する代わりに使用します。
于 2010-10-06T03:01:34.880 に答える
14

これは、必要に応じて成長する目立たない配列のようです。

明示的なメモリ割り当ての使用をやめてください。ほとんどの場合、その必要はありません。std::vectorまたは、必要に応じて自動的に拡張される C++ 標準ライブラリの動的コンテナーを使用します。

null で終わる C スタイルの文字列を使用しているようにも見えます。std::string代わりに使用しないのはなぜですか?

于 2010-10-06T03:00:04.117 に答える
5

C++ では、配列を使用しないでください (動的に割り当てられた場合でも)。

これは std::vector に置き換えられました

C:

char** tmp = (char**)malloc(sizeof(char*) * size);
free(tmp);

// And a correct version of realloc
char** alt = (char**)realloc(sizeof(char*) * newSize);
if (alt)
{
    // Note if realloc() fails then it returns NULL
    // But that does not mean the original object is deallocated.
    tmp = alt;
}

C++ の場合

std::vector<char*>   tmp(size);

// No need for free (destructor does that).
tmp.resize(newSize);
于 2010-10-06T03:05:40.623 に答える
2

Realloc はコンストラクターの呼び出しをあまり気にしないため、new の後に realloc を使用するのは悪い考えのように思えます。より良いアプローチとして vector を使用する必要があります。ベクトルのサイズを変更できます。

于 2010-10-06T03:02:28.747 に答える
2

http://www.cplusplus.com/forum/general/18311/

(要するに、実際には に相当する C++ はありませんreallocが、おそらくvector? を使用したほうがよいでしょう)。

于 2010-10-06T02:56:59.520 に答える
1

手作りの動的配列からベクトルへの切り替えが最初の選択肢として適していると思います。

ベクトルにオブジェクトを直接含めるか、実際のオブジェクトへのポインターを含めるかについては、明確な答えは1つではなく、さまざまな要因によって異なります。

最大の要因は、これらが「エンティティ」オブジェクトと呼ばれるものであるかどうかです。コピーしても意味がありません。典型的な例は、iostreamやネットワーク接続のようなものです。通常、このようなオブジェクトをコピーまたは割り当てる論理的な方法はありません。それがあなたが扱っている種類のオブジェクトである場合、あなたはポインタを格納するのにかなり行き詰まっています。

ただし、一般的に(大まかに)「値オブジェクト」として定義されているものを扱っている場合は、コピーと割り当ては問題なく、オブジェクトをベクトルに直接格納することも問題ありません。このようなオブジェクトの場合、代わりにポインタを格納する主な理由は、メモリを拡張してより多くのオブジェクト用のスペースを確保する必要があるときに、ベクトルがオブジェクトをコピーできる/コピーすることです。オブジェクトが非常に大きくてコピーに費用がかかるためにこれが受け入れられない場合は、ポインタのようなものをベクトルに格納して、安価なコピーと割り当てを取得することをお勧めします。たぶんそれはしませんただし、生のポインターである-それはおそらく、より値のようなセマンティクスを提供するある種のスマートポインターオブジェクトであるため、他のほとんどのコードはオブジェクトを単純な値として扱うことができ、その高価な操作などの詳細はそのままにしておくことができます隠れた。

于 2010-10-06T03:52:04.630 に答える
1

残念ながらrealloc、C++ にはありません (メモリには自明でない構造のオブジェクトや単にコピー不可能なオブジェクトが保持される可能性があるため)。新しいバッファを割り当ててコピーするか、使用方法を学習するstd::vectorstd::stack、自動的にこれを行います。

于 2010-10-06T02:58:13.247 に答える
-1

realloc() に相当する C++ はありません。

最適な用途:

char* new_tmp = new (char*)[mtmp];
for (int n=0;n<min(mtmp,oldSize);n++) new_tmp[n] = tmp[n];
delete [] tmp;  // free up tmp
tmp = new_tmp;

あなたが得ているエラーは、C++ が暗黙的な型キャストに対して寛容ではないためです。

于 2010-10-06T02:58:09.240 に答える