Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Realloc в С++, чем плохо  
V
    Опции темы
sergioK1
Дата 6.3.2012, 17:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Слышу что плохо , а в чем ?, ну есть вектор, ну он же не вместо realloc, по крайне мере в доках никто не говорит что он лучше,
Или Я чего не понимаю?


PM MAIL   Вверх
borisbn
Дата 6.3.2012, 18:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(sergioK1 @  6.3.2012,  17:35 Найти цитируемый пост)
Слышу что плохо , а в чем ?

1) Как минимум realloc не типизирован (читай увеличивается вероятность ошибки).
2) Вместе с указателем на память, выделенную malloc/realloc неплохо бы хранить выделенный размер. У вектора это есть нахаляву
3) При удалении вектора он сам следит за освобождением выделенной им памяти, в случае с malloc/realloc программист должен не забыть вызвать free когда память больше не нужна

на самом деле пунктов больше... я тебе только основные привёл


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
bsa
Дата 6.3.2012, 20:47 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



самый главный забыл.

если у тебя объекты содержат ссылки/указатели на другие объекты в том же массиве, то после realloc возможна ситуация, что размещение массива в памяти изменится, а вот указатели/ссылки внутри объектов нет. В итоге это приведет к серьезным ошибкам. Именно поэтому в С++ realloc нежелателен.
PM   Вверх
volatile
Дата 6.3.2012, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(bsa @  6.3.2012,  20:47 Найти цитируемый пост)
если у тебя объекты содержат ссылки/указатели на другие объекты в том же массиве, то после realloc возможна ситуация, что размещение массива в памяти изменится

Между прочим с вектором картина в точности такая-же.
Так что здесь проблема скорей в ссылках и указателях.
PM MAIL   Вверх
sergioK1
Дата 7.3.2012, 01:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(bsa @ 6.3.2012,  19:47)
самый главный забыл.

если у тебя объекты содержат ссылки/указатели на другие объекты в том же массиве, то после realloc возможна ситуация, что размещение массива в памяти изменится, а вот указатели/ссылки внутри объектов нет. В итоге это приведет к серьезным ошибкам. Именно поэтому в С++ realloc нежелателен.

как это измениться ? 

man 3 realloc 

 void *realloc(void *ptr, size_t size);

realloc() changes the size of the memory block pointed  to  by  ptr  to
       size  bytes.   The contents will be unchanged to the minimum of the old
       and new sizes; newly allocated memory will be uninitialized.  If ptr is
       NULL,  then  the  call is equivalent to malloc(size), for all values of
       size; if size is equal to zero, and ptr is not NULL, then the  call  is
       equivalent  to  free(ptr).   Unless  ptr  is  NULL,  it  must have been
       returned by an earlier call to malloc(), calloc() or realloc().  If the
       area pointed to was moved, a free(ptr) is done.


 где тут сказано про то что размешение измениться ,?



borisbn 

 для стандартных задач это хорошо,
ну а если свой вектор нужен , самое простое перед функцией resize - запись в лог, или мютекс ,?
и есть типы обьестов которые надо закрыть ? 
 
то наследовать? обертку писать ? ну тогда твой класс должен быть темплайтным , 
У меня свой контейнер , и Я счас не знаю что лучше realloc или новый malloc + memcpy + заполнение второй части данными,
Я с этим столькнулся в 99 году на чистом С(Win32),  realloc из-за  падал и пришлось  менять логику что-бы без него , 
там что то обьяснялось ,только Я не помню

С тех пор наверно что-то изменилось ? 





 
 




PM MAIL   Вверх
volatile
Дата 7.3.2012, 01:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(sergioK1 @  7.3.2012,  01:12 Найти цитируемый пост)
где тут сказано про то что размешение измениться ,?


sergioK1, Как вы себе вообще это представляете? Произвольное изменение размера, непрерывного участка памяти ?

Цитата

The function may move the memory block to a new location, in which case the new location is returned. 

realloc
PM MAIL   Вверх
sergioK1
Дата 7.3.2012, 04:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(volatile @ 7.3.2012,  00:58)
Цитата(sergioK1 @  7.3.2012,  01:12 Найти цитируемый пост)
где тут сказано про то что размешение измениться ,?


sergioK1, Как вы себе вообще это представляете? Произвольное изменение размера, непрерывного участка памяти ?

Цитата

The function may move the memory block to a new location, in which case the new location is returned. 

realloc

Xm почему в доке Линукса ничего про это не сказано ?
хотя простой тест показал что это так,

чего то Я не понимаю,  блок памяти передвиниться а ссылки эти разве не в нем? ,  т,е элемент массива это стуктура , где первый 
элемент это его начало , и все ссылки внутри что с ними будет ?
если скажем первый элемент массива имеет ссылку на скажем 8-ой тогда да realloc даст сбой , но в каком случае, изначально 
создавать такой массив архитектурная ошибка IMHO, или задача специфичная, 
и потом элементы могут меняться , кто за ссылками следить будет ?

да и какая разница С или С++? 
PM MAIL   Вверх
borisbn
Дата 7.3.2012, 06:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



>обертку писать ? ну тогда твой класс должен быть темплайтным
Абсолютно ничего плохого здесь не вижу.   
>да и какая разница С или С++?
тут 2 момента: 1) ты задал вопрос именно про Си++ 2) в Си просто нет вектора, new/delete и т.п., поэтому в Си кроме realloc'а ничего и не остаётся. 




--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Dem_max
Дата 7.3.2012, 06:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 4
Всего: 39



в С++ есть только new и delete.


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
LeonidPr
Дата 7.3.2012, 07:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 220
Регистрация: 17.2.2012
Где: г. Чебоксары

Репутация: нет
Всего: 1



Цитата(sergioK1 @ 7.3.2012,  01:12)
...где тут сказано про то что размешение измениться ,?

Здесь
Цитата

The size of the memory block pointed to by the ptr parameter is changed to the size bytes, expanding or reducing the amount of memory available in the block.

The function may move the memory block to a new location, in which case the new location is returned. The content of the memory block is preserved up to the
lesser of the new and old sizes, even if the block is moved. If the new size is larger, the value of the newly allocated portion is indeterminate.

In case that ptr is NULL, the function behaves exactly as malloc, assigning a new block of size bytes and returning a pointer to the beginning of it.

In case that the size is 0, the memory previously allocated in ptr is deallocated as if a call to free was made, and a NULL pointer is returned.

--------------------
pkunzip.zip
PM MAIL   Вверх
bsa
Дата 7.3.2012, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(volatile @  7.3.2012,  00:24 Найти цитируемый пост)
Между прочим с вектором картина в точности такая-же.
Так что здесь проблема скорей в ссылках и указателях. 

Вообще-то вектор копирует содержимое не с помощью memcpy, а с использованием операторов копирования. Поэтому, если класс более или менее вменяемый, то он это дело сам разрулит.
PM   Вверх
sergioK1
Дата 7.3.2012, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(borisbn @ 7.3.2012,  05:19)
>обертку писать ? ну тогда твой класс должен быть темплайтным
Абсолютно ничего плохого здесь не вижу.   
>да и какая разница С или С++?
тут 2 момента: 1) ты задал вопрос именно про Си++ 2) в Си просто нет вектора, new/delete и т.п., поэтому в Си кроме realloc'а ничего и не остаётся.

Да нет, Я говорю не про вектор , это отдельная тема , 

Случайно ++ добавил ,  
Я про realloc vs новый malloc  c переписыванием всего старого массива в новый , 

 т,е, способ 1 
Код

  
     int* arr= (int*) malloc(20* sizeof(int))
     int* arr1 = (int*)realloc(arr, 15*sizeof(int) ;
    for(int i=0;i< 15; i++) 
      arr1[20+i] = новым значениям 


 или 
Код

            int* arr= (int*) malloc(20* sizeof(int))
     int* arr1 = (int*) malloc((20+15)*sizeof(int) ;
     memcpy(arr1,arr,20) ;
    for(int i=0;i< 15; i++) 
      arr1[20+i] = новым значениям 


  
   вместо int* могут быть обьекты AnyClass* object , разница тоько что в С++ typedef не нужен и в С есть только   Struct.
   т,е, чем плохо Я имел ввиду разницу между этими способами, какая разница С или С++?

   
   
bsa :

какая разница что оператор копирования ,это тот же memcopy, только скрыиый, релизации на все равно на асемблере , другово еще не придумали smile 
  

Это сообщение отредактировал(а) sergioK1 - 7.3.2012, 14:53
PM MAIL   Вверх
xvr
Дата 7.3.2012, 15:40 (ссылка) |    (голосов:4) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(sergioK1 @  7.3.2012,  11:30 Найти цитируемый пост)
какая разница что оператор копирования ,это тот же memcopy, 

Оператор копирования - это operator =() и копируемый класс его может переопределить, если это надо (а это часто надо)

Цитата(sergioK1 @  7.3.2012,  11:30 Найти цитируемый пост)
релизации на все равно на асемблере , другово еще не придумали 

Как все запущено  smile 

PM MAIL   Вверх
sergioK1
Дата 7.3.2012, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(xvr @ 7.3.2012,  14:40)

Оператор копирования - это operator =() и копируемый класс его может переопределить, если это надо (а это часто надо)

 Это как бы все знают ,
И что , это всего  лишь для удобсва ,  легче писать , 
А как он реализован? И чем скомилированный код с ним отличаеться от того что без ?

PM MAIL   Вверх
xvr
Дата 7.3.2012, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(sergioK1 @  7.3.2012,  17:00 Найти цитируемый пост)
И чем скомилированный код с ним отличаеться от того что без ?

Отличаться может координально. Вплоть до того, что memcpy работать для данного класса не будет, а operator =() будет.
Например:
Код

class String {
 char buffer[1024];
 char* last_ptr; // Where 'buffer' ends
public:
 String()
  {
   last_ptr=buffer;
  }

 void append(const char* str)
  {
   strcpy(last_ptr,str);
   last_ptr+=strlen(past_ptr);
  }

 void operator=(const String& s)
  {
   memcpy(buffer,s.buffer,sizeof(buffer));
   last_ptr=buffer+(s.last_ptr-s.buffer);
  }
};

Без operator=() этот класс после копирования начнет дописывать строки к оригиналу (откуда копировали), а не к себе.

PM MAIL   Вверх
feodorv
Дата 7.3.2012, 17:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Бог ты мой, да в C те же проблемы. Если, скажем, внутри одной структуры определяются указатели на какие-то значения этой структуры, то беды при realloc не избежать:
Код

struct fullname
{
  char name[MAX_PATH];
  char *fileName;
};

struct fullname *list = NULL;
unsigned int listSize = 0;

BOOL addFile( const char *fullName )
{
  struct fullname *newlist, *current;

  if( listSize == 0 )
    newlist = (struct fullname *) malloc( sizeof(struct fullname) );
  else
    newlist = (struct fullname *) realloc( list, (listSize+1)*sizeof(struct fullname) );
  if( newlist == NULL ) return FALSE;

  list = newlist;
  current = &list[listSize++];

  strncpy( current->name, fullName, sizeof(current->name));
  current->name[sizeof(current->name)-1] = '\0';
  if( (current->fileName = strrchr( current->name, '/')) == NULL ) current->fileName = current->name;

  return TRUE;
}


И ещё пример. Здесь просто запомнили указатель на какой-то элемент списка, а потом сделали realloc:

Код

...
mySupperFile = &list[index];
...
addFile( newFile );
...
printf( "name = %s\n", mySupperFile->name);


Примеры выдуманы, но они демонстрирует опасный код, связанный с realloc. Такие ситуации лечатся тем, что нужно хранить не указатели, а смещения. Но от ошибок никто не застрахован...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
sergioK1
Дата 7.3.2012, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(xvr @ 7.3.2012,  16:10)
Цитата(sergioK1 @  7.3.2012,  17:00 Найти цитируемый пост)
И чем скомилированный код с ним отличаеться от того что без ?

Отличаться может координально. Вплоть до того, что memcpy работать для данного класса не будет, а operator =() будет.
Например:
Код

class String {
 char buffer[1024];
 char* last_ptr; // Where 'buffer' ends
public:
 String()
  {
   last_ptr=buffer;
  }

 void append(const char* str)
  {
   strcpy(last_ptr,str);
   last_ptr+=strlen(past_ptr);
  }

 void operator=(const String& s)
  {
   memcpy(buffer,s.buffer,sizeof(buffer));
   last_ptr=buffer+(s.last_ptr-s.buffer);
  }
};

Без operator=() этот класс после копирования начнет дописывать строки к оригиналу (откуда копировали), а не к себе.

что измениться есть вместо operator = будет метод Сlone ?
а  operator = будет private , для верности , а на С = просто не вызывать, 
да писать так не очень удобно , но компайлеру то какая разница ,?

Код

   void Clone(const String& s)
  {
   memcpy(buffer,s.buffer,sizeof(buffer));
   last_ptr=buffer+(s.last_ptr-s.buffer);
  }
};


Это сообщение отредактировал(а) sergioK1 - 7.3.2012, 17:49
PM MAIL   Вверх
bsa
Дата 7.3.2012, 17:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(feodorv @  7.3.2012,  18:35 Найти цитируемый пост)
Бог ты мой, да в C те же проблемы. 

C отличается от С++ тем, что на тебе лежит больше обязанностей по контролю правильности.
Цитата(sergioK1 @  7.3.2012,  18:40 Найти цитируемый пост)
что измениться есть вместо operator = будет метод Сlone ?

Изменится то, что стандартные методы работать с таким классом не будут. Зачем усложнять себе жизнь?
PM   Вверх
sergioK1
Дата 7.3.2012, 21:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(feodorv @ 7.3.2012,  16:35)
Такие ситуации лечатся тем, что нужно хранить не указатели, а смещения. Но от ошибок никто не застрахован...

Или писать свой  wrapper realloc он же Clone и копировать указатели/ссылки , или не копировать , в зависимости от задачи, 
в С++ это копи конструктор ,  но это  не значит что realloc это плохо,  

в случае с vector возникают  теже самые проблемы , 


feodorv - спасибо прояснил ситуацию , 
Вопрос решен 




Это сообщение отредактировал(а) sergioK1 - 8.3.2012, 00:14
PM MAIL   Вверх
xvr
Дата 8.3.2012, 09:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(sergioK1 @  7.3.2012,  17:40 Найти цитируемый пост)
а  operator = будет private , для верности , а на С = просто не вызывать, 
да писать так не очень удобно , но компайлеру то какая разница ,?

Разница в том, что operator= будет вызываться автоматически компилятором (там, где надо), а Clone вам придется звать вручную. При этом запросто можно забыть и не позвать этот самый Clone (человеку свойственно ошибаться). А вот компилятор не ошибается. Ну и в конце концов у вас может и не быть возможности этот самый Clone позвать (как уже упоминал bsa, например при использовании stl контейнеров)

PS. В 99% реализации realloc внутри сделает free и malloc если его попросят увеличить выделенный блок, так что его использование не дает никаких преимуществ


PM MAIL   Вверх
sergioK1
Дата 8.3.2012, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(xvr @ 8.3.2012,  08:37)
PS. В 99% реализации realloc внутри сделает free и malloc если его попросят увеличить выделенный блок, так что его использование не дает никаких преимуществ


На чем это утверждение основано ?  
мне как в суде аргуметы нужны и факты  smile , 

Это сообщение отредактировал(а) sergioK1 - 8.3.2012, 10:42
PM MAIL   Вверх
Alexeis
Дата 8.3.2012, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 12
Всего: 459



Цитата(sergioK1 @  8.3.2012,  11:20 Найти цитируемый пост)
На чем это утверждение основано ? 

Потому же менеджер кучи не резервирует дополнительного места после блока выделенной памяти. Расширение будет только если освободили память строго за текущим блоком при этом освобожденный блок был больше чем нужно для роста. Такое событие маловероятно. Если хотите реально иметь возможность выделять память с возможностью роста, то такое поведение можно сделать средствами ОС, в частности в Windows можно зарезервировать адресное пространство, но выделить только столько сколько нужно, а при необходимости до выделить память по зарезервированным адресам. Тогда получиться непрерывный кусок расширяемый кусок. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
sergioK1
Дата 8.3.2012, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(Alexeis @ 8.3.2012,  10:03)
Цитата(sergioK1 @  8.3.2012,  11:20 Найти цитируемый пост)
На чем это утверждение основано ? 

Потому же менеджер кучи не резервирует дополнительного места после блока выделенной памяти. Расширение будет только если освободили память строго за текущим блоком при этом освобожденный блок был больше чем нужно для роста. Такое событие маловероятно. Если хотите реально иметь возможность выделять память с возможностью роста, то такое поведение можно сделать средствами ОС, в частности в Windows можно зарезервировать адресное пространство, но выделить только столько сколько нужно, а при необходимости до выделить память по зарезервированным адресам. Тогда получиться непрерывный кусок расширяемый кусок.

Это понятно ,но Я не уверен что он вызывает имеено malloc , если бы так то realloc был бы не нужен ,
а не другие механизмы , более низнего уровня,  
PM MAIL   Вверх
bsa
Дата 8.3.2012, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(sergioK1 @  8.3.2012,  12:36 Найти цитируемый пост)
Это понятно ,но Я не уверен что он вызывает имеено malloc , если бы так то realloc был бы не нужен ,
а не другие механизмы , более низнего уровня,   

malloc/realloc/calloc/free работают с "кучей" (new/delete тоже, кстати), которая реализуется средствами стандартной библиотеки. К API системы это не имеет отношения (точнее, API используется только для изменения размеров собственно кучи). А куча - это как файловая система на диске, только без возможности фрагментации. Увеличить конкретный блок можно только:
или если после него есть свободное место
или если он находится в конце кучи, а другого подходящего куска в куче нет, в этом случае куча будет увеличена и блок будет увеличен соответственно.

Это сообщение отредактировал(а) bsa - 8.3.2012, 14:29
PM   Вверх
xvr
Дата 9.3.2012, 10:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(sergioK1 @  8.3.2012,  10:20 Найти цитируемый пост)
На чем это утверждение основано ?  

На изучении некоторого количества сорцов RTL и на здравом смысле. Если вы хотите, что бы realloc мог сделать что то помимо free/malloc вам надо самому следить за тем, что и в какой последовательности вы просите расположить на куче. realloc не может перераспределить уже выделенную память, поэтому, если после куска, который вы хотите увеличить, что то уже лежит, то никаких вариантов кроме free/malloc уже не остается

PM MAIL   Вверх
sergioK1
Дата 10.3.2012, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(xvr @ 9.3.2012,  09:06)
Если вы хотите, что бы realloc мог сделать что то помимо free/malloc вам надо самому следить за тем, что и в какой последовательности вы просите расположить на куче. realloc не может перераспределить уже выделенную память, поэтому, если после куска, который вы хотите увеличить, что то уже лежит, то никаких вариантов кроме free/malloc уже не остается

Не понял, если  если после куска, который вы хотите увеличить, что то уже лежит, то логике ,realloc сам вызовет malloc + memcpy,
или какой то свой механизм/алгоритм, 
Я ж не знаю лежит что-то после куска или нет , счас может лежать через 5 минут нет , 

про самому следить за тем, что и в какой последовательности вы просите расположить на куче это как ? 

PM MAIL   Вверх
bsa
Дата 10.3.2012, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(sergioK1 @  10.3.2012,  18:53 Найти цитируемый пост)
Не понял, если  если после куска, который вы хотите увеличить, что то уже лежит, то логике ,realloc сам вызовет malloc + memcpy,
или какой то свой механизм/алгоритм,
Ты все понял. После malloc+memcpy+free будет выделен НОВЫЙ участок памяти, и старые указатели станут неверны.
Цитата(sergioK1 @  10.3.2012,  18:53 Найти цитируемый пост)
Я ж не знаю лежит что-то после куска или нет , счас может лежать через 5 минут нет
Вот именно.
Цитата(sergioK1 @  10.3.2012,  18:53 Найти цитируемый пост)
про самому следить за тем, что и в какой последовательности вы просите расположить на куче это как ? 
Написать свой собственный менеджер кучи.
PM   Вверх
sergioK1
Дата 12.3.2012, 00:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



он и в С не особо то и нужен, все равно нужно клонировать объект (хоть с =() , хоть и без ),
тут вопрос закрыт

еще момент , раз уж зашла речь за вектор , 

Код

 template<class T, class U = std::allocator<T> >
 class MyVector : public vector<T,U>{      
 }


стандартный вектор на два множит , мне надо 100 прибавлять,   правильно алокатор писать ?
должен быть свой класс наследник std::allocator? , какие методы перегружать ? или у вектора resize перегрузить ?



Это сообщение отредактировал(а) sergioK1 - 12.3.2012, 00:32
PM MAIL   Вверх
xvr
Дата 12.3.2012, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(sergioK1 @  12.3.2012,  00:01 Найти цитируемый пост)
стандартный вектор на два множит ,

Вектор имеет право изменять размер буфера как ему захочется, но снаружи это не видно. size() всегда будет возвращать размер реальных данных. А вот capacity() будет возвращать нечто большее.

Цитата(sergioK1 @  12.3.2012,  00:01 Найти цитируемый пост)
правильно алокатор писать ?

Это не поможет, вектор стартегию выделения памяти (с запасом) на allocator не отдает.


Цитата(sergioK1 @  12.3.2012,  00:01 Найти цитируемый пост)
 мне надо 100 прибавлять,

Управляйте размером и резервацией в векторе явно (resize() и reserve())

Цитата(sergioK1 @  12.3.2012,  00:01 Найти цитируемый пост)
какие методы перегружать ?

Никакие. У STL контейнеров нет виртуальных методов

PM MAIL   Вверх
mes
Дата 12.3.2012, 09:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(sergioK1 @  11.3.2012,  23:01 Найти цитируемый пост)
 мне надо 100 прибавлять

из простого, написать свой (внешний) push_back, который будет ресайзить по нужной стратегии... 





--------------------
PM MAIL WWW   Вверх
sergioK1
Дата 12.3.2012, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(xvr @ 12.3.2012,  07:48)

Цитата(sergioK1 @  12.3.2012,  00:01 Найти цитируемый пост)
 мне надо 100 прибавлять,

Управляйте размером и резервацией в векторе явно (resize() и reserve())

как это будет на С++ не словах, smile  ,   

mess , как ?, внутри вектора есть обьест, который при добавке умножает память на 2,  как мне этот обьект получить ?
пример если не трудно положите 




Это сообщение отредактировал(а) sergioK1 - 12.3.2012, 09:32
PM MAIL   Вверх
mes
Дата 12.3.2012, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(sergioK1 @  12.3.2012,  08:26 Найти цитируемый пост)
mess , как ?

mes smile

Цитата(sergioK1 @  12.3.2012,  08:26 Найти цитируемый пост)
внутри вектора есть обьест, который при добавке умножает память на 2,  как мне этот обьект получить ?

самого вектора достаточно..

Цитата(sergioK1 @  12.3.2012,  08:26 Найти цитируемый пост)
пример если не трудно положите 

http://liveworkspace.org/code/ba491fe1c0f7...622e759b9282854


--------------------
PM MAIL WWW   Вверх
xvr
Дата 12.3.2012, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(sergioK1 @  12.3.2012,  09:26 Найти цитируемый пост)
как это будет на С++ не словах,

Код

void my_push_back(vector<int>& dst, int value)
{
 if (dst.size()+1>=dst.capacity()) dst.reserve(dst.capacity()+100);
 dst.push_back(value);
}


PM MAIL   Вверх
volatile
Дата 13.3.2012, 02:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



В векторе же не только пуш-бек, добавлять может
там еще придется "костылировать"... smile

Добавлено через 3 минуты и 54 секунды
sergioK1, вам имхо нужен не вектор.
рассмотрите возможность использования deque.
PM MAIL   Вверх
sergioK1
Дата 13.3.2012, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(volatile @ 13.3.2012,  01:09)
В векторе же не только пуш-бек, добавлять может
там еще придется "костылировать"... smile

Добавлено @ 02:13
sergioK1, вам имхо нужен не вектор.
рассмотрите возможность использования deque.

там еще придется "костылировать" 
А это на каком языке  ?  smile 

Alocator для чего? только не говорите что мне он не нужен (так многие говорят, и пугают им как бабой ягой  smile  ) 
как с ним работать? , примерчик если не сложно





PM MAIL   Вверх
xvr
Дата 13.3.2012, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(sergioK1 @  13.3.2012,  12:18 Найти цитируемый пост)
Alocator для чего?

Для выделения/удаления памяти и инициализации объектов на ней. Стандартный Allocator аналогичен связке из new/delete и конструктора и деструктора для произвольного класса (для этого там используются шаблонные функции).
Свой Allocator нужен если вы хотите изменить стандартный менеджер памяти для конкретных экземпляров контейнера (например сделать память на пуле, а не в куче)
На внутреннее функционирование контейнеров Allocator не влияет

Добавлено через 43 секунды
Цитата(sergioK1 @  13.3.2012,  12:18 Найти цитируемый пост)
А это на каком языке  ?  smile 

На С++ - std::deque<> - стандартный контейнер

PM MAIL   Вверх
sergioK1
Дата 13.3.2012, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



1) Что значит фраза из предыдушего поста , "там придеться костылить"

2) разницу между деком и вектором не понимаю  , дока пишеть что more efficient , 
   видимо  доступ вместо O(n)   O(log2) или  O(1) ,  ну и инсерт хуже соответсвенно ,  методы у обоих класов одинаковые, 
 а  что там мор когда и  на сколько?,
PM MAIL   Вверх
bsa
Дата 13.3.2012, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



sergioK1, 
Цитата
Double-ended queues (or deques) are similar to vectors, except that they allow fast insertions and deletions at both the beginning and the end of the container and that they are not required to be contiguous.
Deques are commonly implemented as lists of individual dynamically allocated arrays of some convenient size, e.g. memory page size. This guarantees constant time access, amortized constant time insertion and deletion at either end of the deque (a new array may have to be allocated), and linear time insertion and deletion from the middle of the deque.
Если не понятно: deque гарантирует аммортизированное константное время вставки в начало и конец контейнера. У вектора переаллокация вызывает полное копирование всего массива. У deque копирования не будет, а просто довыделится память под следующие несколько элементов...
PM   Вверх
volatile
Дата 14.3.2012, 03:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(sergioK1 @  13.3.2012,  14:02 Найти цитируемый пост)
Что значит фраза из предыдушего поста , "там придеться костылить"

то что, в вектор добавлять придется не стандартной процедурой:
vector.push_back (element); а костылем: 
my_push_back (vector, element);
Кроме-то в вектор могут добавлять и другие методы. Их тоже нужно переписывать.
Извиняюсь за придуманное слово "костылировать"  smile мне показалось, что оно хорошо отражает суть дела.

Насчет дека, добалю к тому что сказал bsa, у него есть один недостаток, по сравнению с вектором: Данные расположены не непрерывно. Второй недостаток это несколько медленное время доступа к центральным элементам. (По опыту скажу, не на много медленее, по крайней мере в студии)
Преимущества: Выделят блоки примерно так как вы хотите, порциями. Все прежде выделенные блоки остаются на своих местах, никаких гигантских перераспределений памяти (как в векторе) не бывает. Вообще ведет себя довольно ровно, в отличии от вектора. Последний,  при достаточном размере, может в буквальном смысле подвесить программу на n-ое кол-во секунд, с требованиями трехкратного запаса памяти. Как это происходит: Допустим вектор имеет размер 1000, постпупил еще 1 элемент, в этот момент он затребует 2000 памяти, (1000+2000=3000), потом откопирует, и только потом освободит 1000. То есть, есть момент когда нужен 3-кратный запас по памяти. Кстати, в вашем случае с my_push_back(), нужен будет 2 кратный+100 запас (1000+1100=2100), но и перераспределения будут происходить чаще.
PM MAIL   Вверх
sergioK1
Дата 14.3.2012, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(volatile @ 14.3.2012,  02:13)
То есть, есть момент когда нужен 3-кратный запас по памяти. Кстати, в вашем случае с my_push_back(), нужен будет 2 кратный+100 запас (1000+1100=2100), но и перераспределения будут происходить чаще.

Так Deck  - это получаеться линк лист где вместо нода массив каждый раз разного размера  где последний елемент , 
 указывает на первый в следующем ,  т,е в сранение с просто линк листом , доступ к елеметам  внутри блока будет О(1)(по индексу), 
 т,е у линк листа   это всегдаO(n)  а в деке  как , зная размер каждого блока , сразу будет искать в нужном , ?
 т,е O(average(blockSize) , т,е, при вызове скажем D[5296]  он знает что надо пойти в 38 блок ,  а там все 150 элеметов,
 но это если данные порциями приходят,  скажем по 50 элеметов в среднем , но если придут по 5 то это мало что даст, 
  
 т,е, в плане выделения памяти он ведет себя как линк лист 
 в плане доступа как обычный   массив, 

 т,е применять его можно когда четко знаешь что у тебя за данные ,

Кажеться сам себе ответил  smile 

да еще 
Так тут не один способ релизаций может быть , у каждого поставщика компайлера свой, 

 а вектор (если нельзя изменить *2 ) это зло smile  , не верю что уважающий себя сервер его пользует , 
 наверняка есть либы где , push back и resize виртуальные , или Я чего пропустил ,

   





PM MAIL   Вверх
mes
Дата 14.3.2012, 21:38 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(sergioK1 @  14.3.2012,  11:39 Найти цитируемый пост)
 а вектор (если нельзя изменить *2 ) это зло

это используется для неизвестного кол-ва данных.. Если есть предположения о кол-ве входящих данных, то нужна своя стратегия увелечения данных.. Более того бывают случаи, когда удобно пользоваться не одним типом контейнера, а смешанным в зависимости от подзадачи..  Например считать данные в деку, чтоб избежать лишнего копирования при перераспределении, а после поместить все в вектор уже нужного размера,   чтоб иметь возможность прямого доступа..



--------------------
PM MAIL WWW   Вверх
sergioK1
Дата 14.3.2012, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет





Все ясно всем спасибо, 
выяснил даже больше чем хотел, 
закрываем лавочку  smile 


Это сообщение отредактировал(а) sergioK1 - 14.3.2012, 22:46
PM MAIL   Вверх
bsa
Дата 19.3.2012, 13:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(sergioK1 @  14.3.2012,  13:39 Найти цитируемый пост)
Так Deck  - это получаеться линк лист где вместо нода массив каждый раз разного размера  где последний елемент , 
 указывает на первый в следующем ,  т,е в сранение с просто линк листом , доступ к елеметам  внутри блока будет О(1)(по индексу), 
 т,е у линк листа   это всегдаO(n)  а в деке  как , зная размер каждого блока , сразу будет искать в нужном , ?

deque (от double ended queue - двусторонняя очередь) это примерно вектор указателей на фиксированные вектора. Т.е. когда ты добавляешь в дек данные, а у него нет под них места, то выделяется блок данных фиксированного размера, и в него уже добавляются данные. Указатель на свежевыделенный блок попадает в вектор указателей. Для вычисления элемента по индексу достаточно ему выполнить: ptr_vector[idx / blk_data_size][idx % blk_data_size];
Как ты понимаешь, время константно.

Это сообщение отредактировал(а) bsa - 19.3.2012, 13:27
PM   Вверх
sergioK1
Дата 19.3.2012, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(bsa @ 19.3.2012,  12:27)
Цитата(sergioK1 @  14.3.2012,  13:39 Найти цитируемый пост)
Так Deck  - это получаеться линк лист где вместо нода массив каждый раз разного размера  где последний елемент , 
 указывает на первый в следующем ,  т,е в сранение с просто линк листом , доступ к елеметам  внутри блока будет О(1)(по индексу), 
 т,е у линк листа   это всегдаO(n)  а в деке  как , зная размер каждого блока , сразу будет искать в нужном , ?

deque (от double ended queue - двусторонняя очередь) это примерно вектор указателей на фиксированные вектора. Т.е. когда ты добавляешь в дек данные, а у него нет под них места, то выделяется блок данных фиксированного размера, и в него уже добавляются данные. Указатель на свежевыделенный блок попадает в вектор указателей. Для вычисления элемента по индексу достаточно ему выполнить: ptr_vector[idx / blk_data_size][idx % blk_data_size];
Как ты понимаешь, время константно.


Понимаю , сам такое когда-то изобретал на С , 
Реализацию где посмотреть ? от поставщика , 

Это сообщение отредактировал(а) sergioK1 - 19.3.2012, 16:11
PM MAIL   Вверх
bsa
Дата 19.3.2012, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



sergioK1, начни с хидера deque. А дальше уже тебя IDE направит.
PM   Вверх
sergioK1
Дата 19.3.2012, 23:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 30.1.2011

Репутация: нет
Всего: нет



Цитата(bsa @ 19.3.2012,  15:10)
sergioK1, начни с хидера deque. А дальше уже тебя IDE направит.

OK, смотрю 

thanks 




PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1099 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.