186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
|
|
1 | |
realloc и вызов конструктора20.05.2011, 13:52. Показов 20987. Ответов 35
Метки нет Все метки)
(
здраствуйте! мне препод сказал, что можно выделить память оператором new, а потом довыделить её с помощью realloc и каким-то образом вызвать конструкторы для новой памяти(ну или это я так его понял
![]() задание вобще такое:
0
|
|
20.05.2011, 13:52 | |
Ответы с готовыми решениями:
35
вызов конструктора вызов конструктора Вызов конструктора Вызов конструктора копий |
В астрале
![]() 8041 / 4798 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
|
|
20.05.2011, 13:55 | 2 |
pito211, Ага. Можно. А еще стрелять себе в голову тоже не запрещается... Это я на тему new и realloc. realloc не реагирует на конструкторы. Да плюс к тому new выделяет свободную память, а realloc/malloc/calloc выделяют память в куче.
1
|
![]() ![]() |
|
20.05.2011, 14:27 | 4 |
Нельзя вперемешку использовать new/delete и malloc/realloc/free. Точнее можно, но с непредсказуемыми последствиями. В Си++ нет встроенной конструкции для перевыделения памяти, а потому такое делается через malloc/realloc. Если препод бестолковый из разряда "у меня работает, значит можно", то сделай new/realloc, но для себя надо понимать, что это интерфейсы разных уровней, которые в общем случае не следует перемешивать
Добавлено через 2 минуты На самом деле вызов конструктора - это снаружи new, а не изнутри (т.е. вызов конструктора ставит компилятор, а не реализация оператора new). По поводу того, что "это тот же malloc" - это постфактум в реализациях. Но, как мне кажется, никто не гарантирует, что new это в чистом виде обёртка вокруг malloc'а и что там никаких дополнительных действий не делается
1
|
20.05.2011, 14:41 | 5 |
Препод как раз толковый. Думаю тут задача стоит изучить "изнутри" оператор new как он работает.
А по теме: для своего класса надо переопределить new. Добавлено через 12 минут да с вызовом конструктора внутри погорячился... ибо на стеке нет никакого new но конструктор вызывается, следовательно new тут не причем ну еще проверки и вызов исключения если нехватает памяти: Код
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) { // try to allocate size bytes void *p; while ((p = malloc(size)) == 0) if (_callnewh(size) == 0) { // report no memory static const std::bad_alloc nomem; _RAISE(nomem); } return (p); }
1
|
В астрале
![]() 8041 / 4798 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
|
|
20.05.2011, 15:00 | 6 |
oxotnik, Ну одна из реализаций. Кто сказал что она единственная?
Добавлено через 4 минуты Тем более что реализовать что-то вроде realloc средствами С++ ну вообще не проблема. Правда он будет не оптимизированный да и вообще, но все же.
1
|
186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
|
|
20.05.2011, 15:16 [ТС] | 7 |
вы уже чё то не то обсуждаете
![]() лучше расскажите как без кода, в общих чертах, если не затруднит
0
|
![]() ![]() |
|
20.05.2011, 15:23 | 8 |
В первом посте написано: "препод сказал, что можно выделить память оператором new, а потом довыделить её с помощью realloc", а в задании про переопределение оператора new ничегоне сказано. Так что хз что тут: либо препод неправильный, либо автор слова препода исковеркал
Проверки фиг с ними. Я имел в виду то, что new по аналогии с malloc'ом ожет выделять чуть больше памяти, чтобы хранить воспомогательную информацию и при этом возвращать немного не то, что вернул malloc. В этом отношении при комбинации new/realloc можно конкретно накосячить В одной из тем обсуждали, что встроенных аналогов realloc'а нет, только всякие контейнеры типа std::vector (которые по сути обёртки над malloc/realloc)
1
|
20.05.2011, 15:30 | 9 |
Посмотрел реализацию gcc Студии, борланда, везде практически одно и тоже.
Выделяется память через malloc делаются проверки, и указатель возвращается. Под какую такую информацию надо резервировать доп. память? А что тогда sizeof будет показывать?
0
|
![]() ![]() |
|||||||||||
20.05.2011, 15:45 | 10 | ||||||||||
![]() Решение
glibc'шная реализация malloc'f при каждом обращении выделяет памяти больше, чем нужно. И в дополнительную память кладёт магическое число, чтобы делать контроль внутри realloc'а и free. Схематично что-то типа того:
Ровно таким же образом могут быть реализованы операторы new и delete. Т.е. new внутри себя использует malloc, но наружу может отдать немного не то, что вернул malloc Пример, как это работает в glibc под linux'ом:
Код
$ gcc t.c $ ./a.out *** glibc detected *** ./a.out: free(): invalid pointer: 0x0804b030 *** Aborted
6
|
![]() ![]() |
|
20.05.2011, 16:01 | 12 |
Например, там же, где и магическое число. Это всё зависит от реализации malloc'а. Реально malloc внутри себя выделяет память с точностью до страницы (чтобы при куче маленьких выделений памяти поменьше обращаться к системе). Там ещё целая куча всяких наноалгоритмов
Вот, например, одна из реализаций malloc'а: тыц Добавлено через 35 секунд sizeof от чего?
1
|
186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
|
|
20.05.2011, 16:15 [ТС] | 14 |
спасибо всем за развёрнутый ответ
![]()
0
|
В астрале
![]() 8041 / 4798 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
|
|
20.05.2011, 16:24 | 15 |
pito211, Да элементарно. Подход как у вектора.
Используем себе массив - нужно больше - вызываем специальную самописную функцию, перераспределяющую память, путем создания нового указателя (с большим размером выделенной памяти) и копирования туда элементов, удалением старого указателя и присваиванием старому указателю адрес нового, изменение переменной размера для старого. Ну и собственно-то все.
1
|
186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
|
||||||
20.05.2011, 16:34 [ТС] | 16 | |||||
ну я понял, просто я думал есть какие-то более рациональные варианты. Пока вы охотник с Evg обсуждали тут... Я накатал следующее:
0
|
![]() ![]() |
|
20.05.2011, 16:41 | 17 |
![]() Решение
Это не есть хорошо, потому что чем больше памяти будешь выделять, тем больше будет вероятность того, что память жрётся неэффективно (да ещё и экспотенциально). Обычно делают так, что выделяют некий квант (например, 1024 элемента) и выделяют память квантами. Т.е. изначально 1024 элемента, после того, как исчерпали - увеличиваем на 1024 элемента.
Ещё более грамотным будет плавающее значение кванта в зависимости от размера структуры. Т.е.определить квант, например, в (4096 / sizoef элемента). В этом случае независимо от размера элемента у тебя память будет расходоваться кусками по 4096 байт (что составляет одну страницу памяти - система работает с такими же квантами). Но тут будут ньюансы: если размер элемента больше 4096 или когда 4096 нацело не делится. Тут надо более аккуратно работать, а потому такой вариант годится скорее для саморазвития, чем для сдачи задания (потому что чем сложнее реализация, тем больше можно наделать ошибок)
5
|
В астрале
![]() 8041 / 4798 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
|
|
20.05.2011, 16:57 | 18 |
Evg, Ну в STL множитель где-то 1.5 как пишет Саттер. Да и в MSVS реализации вектора было именно так.
1
|
186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
|
|
20.05.2011, 17:07 [ТС] | 19 |
а лафоре хвалит коэффицент х2 в главе про класс алокатор
говорит удивительнорго эффективный ![]()
0
|
![]() ![]() |
|
20.05.2011, 17:23 | 20 |
По скорости работы - скорее всего будет эффективнее. По памяти - большой вопрос. Хотя в наши дни считается, что скорость важнее потребляемой памяти, потому что её много.
Реально конечно же всё зависит от конкретной задачи. Если один и тот же массив после заполнения постоянно очищается и перезаполняется - то ему пофиг, потому что память уже выделена и при освобождении массива память как правило НЕ отдаётся системе (т.е. при дальнейшем заполнении массива к сиситеме мы уже не бдем обрашщаться, т.к. память у нас есть). Если задача такая, что есть много массивов, но заполняются редко, то надо идти по пути экономии памяти, потому что в скорости от этого навара будет мало. Если массивы сильно заполняются, но живут недолго, то идти надо по пути максимальной скорости работы (потому что память быстро возвращается и её незачем сильно экономить). Собственно, потому и во всех контейнерах можно подсунуть свой аллокатор, который "знает", как работает твоя конкретная задача и наиболее оптимальным образом расходует память. А дефолтный аллокатор - это уже на усмотрение разработчиков. Видимо, как я писал выше, на сегодняшний день считается, что в дефолтном среднестатистическом случае экспотенциальный режим выгоднее
1
|
20.05.2011, 17:23 | |
Помогаю со студенческими работами здесь
20
Вызов базового конструктора Неоднозначный вызов конструктора
Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |