11

在较早的问题中,我询问了类型转换指针,但被引导到使用 C++ 分配系统而不是 mallocs 的更好解决方案。(我正在将一些 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

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

(简而言之 - 没有真正的 C++ 等价于realloc,但也许你最好使用vector?)

于 2010-10-06T02:56:59.520 回答
2

Realloc 并不真正关心调用构造函数,因此在 new 之后使用 realloc 似乎是个坏主意。您应该将向量作为更好的方法。您可以调整矢量的大小。

于 2010-10-06T03:02:28.747 回答
1

不幸的是,realloc在 C++ 中没有(因为内存可能包含非平凡构造或只是不可复制的对象)。分配新缓冲区并复制或学习使用,std::vector或者std::stack会自动为您执行此操作。

于 2010-10-06T02:58:13.247 回答
1

我会考虑从手工制作的动态数组切换到向量是一个不错的首选。

至于向量是否应该直接包含对象,或者包含指向实际对象的指针,没有一个明确的答案——这取决于许多因素。

最大的一个因素是这些是否是我所说的“实体”对象——对于那些复制毫无意义的对象。一个典型的例子是 iostream 或网络连接。通常没有合乎逻辑的方法来复制或分配这样的对象。如果那是您正在处理的那种对象,那么您几乎会陷入存储指针的困境。

但是,如果您正在处理通常(松散地)定义为“值对象”的内容,则复制和分配就可以了,并且将对象直接存储在向量中就可以了。对于这样的对象,存储指针的主要原因是当向量必须扩展内存以为更多对象腾出空间时,它可以/将复制对象。如果您的对象太大且复制成本太高以至于无法接受,那么您可能希望在向量中存储类似指针的东西以获得廉价的复制和分配。很有可能不会虽然是一个原始指针 - 它可能是某种智能指针对象,提供更多类似值的语义,因此大多数其他代码可以将对象视为一个简单值,并且其昂贵操作的细节等可以保留隐。

于 2010-10-06T03:52:04.630 回答
-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 回答