Вопрос

В более ранний вопрос я спросил о типоразмерных указателях, но был направлен на лучшее решение использования системы распределения C ++ вместо Mallocs. (Я преобразую какой-то код 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:

Хорошо, консенсус, который я получаю, это то, что я должен бросить свое текущее решение (которое я открыт для этого).

Просто чтобы убедиться, что я правильно понимаю, вы, ребята, означают, что вместо массива указателей на объекты я должен просто иметь вектор, содержащий сами объекты?

Это было полезно?

Решение

C позволяет void* быть неявно преобразованным в любой указатель. C ++ не так, так что если вы используете realloc, Вы должны отбрасывать результат к соответствующему типу.

Но что более важно, используя realloc по указателю, возвращенному new[] не определено поведение. И нет прямого C ++ - стиль эквивалент realloc.

Ваш выбор, по крайней мере, для самых идиоматических:

  • Придерживаться malloc/realloc/free и бросить указатели.
  • Использовать new[] + delete[] вместо realloc
  • Использовать std::vector<std::string> Вместо того, чтобы управлять вашей собственной памятью.

Другие советы

Похоже, это не безработный массив, который растет по мере необходимости.

Хватит с помощью явного распределения памяти, вы почти наверняка не нуждаетесь в этом. Использовать std::vector Или другой из динамических контейнеров C ++ стандартных библиотеки, которые автоматически растут по мере необходимости для вас.

Это также выглядит так, как будто вы используете NULL-LACKIND Строки C-стиля C. Почему не используется std::string вместо?

В C ++ вы не должны использовать массивы (даже динамически выделенные).

Это было заменено на std :: вектор

В 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);

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

(Короче - нет никакого эквивалента C ++ для realloc, но, может быть, вы будете лучше использовать vector?)

RealLoc не позаботится о том, чтобы позвонить конструкторам, поэтому используя Realloc после нового кажутся плохой идеей. Вы должны идти на вектор в качестве лучшего подхода. Вы можете изменить размер векторов.

К сожалению, нет realloc в C ++ (из-за того, что память может удерживать нетривиально, построенные или просто не копироваемые объекты). Либо выделите новый буфер и копируйте или научитесь использовать std::vector или std::stack Это сделало бы это для вас автоматически.

Я бы рассмотрел переключение с ручной работы динамического массива до вектора хорошего первого выбора.

Что касается того, следует ли вектору напрямую объекты напрямую или содержать указатели на фактические объекты, нет одного окончательного ответа - это зависит от ряда факторов.

Самый большой фактор - это то, что я бы назвал «сущностью» объектами - те, для которых копирование не имеет смысла. Классический случай в точке был бы чем-то вроде ioStream или сетевой связи. Там, как правило, нет логичного способа скопировать или назначить такой объект. Если это тот тип объекта, с которым вы имеете дело, вы в значительной степени застряли на хранилище указателей.

Если, однако, вы имеете дело с тем, что обычно (свободно), определенные как «ценные объекты», копирование и назначение будет хорошо, и сохранение объектов непосредственно в векторе будет в порядке. При таких объектах основная причина хранения указателей вместо этого было бы то, что вектор CAN / будет копировать объекты вокруг, когда он должен расширить память, чтобы освободить место для большего количества объектов. Если ваши объекты настолько большие и дорогие, чтобы скопировать, что это недопустимо, тогда вы можете хранить что-то указанное в векторе, чтобы получить дешевое копирование и назначение. Скорее всего, это будет нет Быть необработанным указателем, хотя - это, вероятно, будет каким-то образом умного объект указателя, который обеспечивает более ценноподобную семантику, поэтому большинство других кодов может относиться к объекту как простое значение, а детали его дорогих операций и такими могут оставаться скрытый.

Там нет C ++ эквивалента Realloc ().

Лучшее использование:

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 ++ менее снисходительно с помощью неявного литья типа.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top