Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 153, средняя оценка - 4.65
pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
#1

realloc и вызов конструктора - C++

20.05.2011, 13:52. Просмотров 18754. Ответов 35
Метки нет (Все метки)

здраствуйте! мне препод сказал, что можно выделить память оператором new, а потом довыделить её с помощью realloc и каким-то образом вызвать конструкторы для новой памяти(ну или это я так его понял). Как это можно сделать?

задание вобще такое:
Во всех вариантах необходимо первоначально создать шаблон класса для работы с массивом произвольного типа данных. Шаблон должен включать:
указатель, хранящий адрес размещения массива в динамической памяти;
целочисленную переменную, показывающую количество занятых элементов массива;
конструктор без параметров, создающий динамический массив заданного типа, с нулевым количеством занятых элементов;
конструктор копирования;
очистку массива;
метод «обработки массива»;
деструктор.
Далее на основе данного шаблона создать класс для работы со строкой символов, специализировав метод «обработки массива» для вашей конкретной задачи.
я хотел класс allocator использовать, но нельзя((. Пока на примете только один вариант - выделять с помощью new и как только память заполниться выделять участок в два раза крупнее копировать старые данные и подчищать за ними. Есть ещё варианты?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.05.2011, 13:52
Здравствуйте! Я подобрал для вас темы с ответами на вопрос realloc и вызов конструктора (C++):

realloc - C++
Столкнулся с проблемой при значениях nStgElm близких к 1000 происходит ошибка выеления памяти WIN32_FIND_DATA * pDATA = (WIN32_FIND_DATA...

Доступность копирующего конструктора - C++
Всем привет. Не так давно в одной из тем была упомянута статья Герба Саттера Variable Initialization – or Is It?. По статье...

Наследование конструктора от переменного шаблона - C++
В С++ 11 появилась возможность унаследовать конструктора базового класса при помощи конструкции using. class A { public: ...

[template] почему код не компилируется без конструктора - C++
добрый вечер. вопрос поместил прямо в коде. http://rextester.com/AESO94403 #include <iostream> #include <string> #include...

[C++] Взятие адреса конструктора. Физическое время существование объекта. - C++
1. конструктор. class A { int a; public: A():a(555){}; ~A(){}

Почему лучше инициализировать объекты класса во время инициализации конструктора? - C++
Имеется класс Rnd: class Rnd { public: Rnd::Rnd(int x); private: int val; };

35
ForEveR
В астрале
Эксперт С++
7978 / 4737 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
20.05.2011, 13:55 #2
pito211, Ага. Можно. А еще стрелять себе в голову тоже не запрещается... Это я на тему new и realloc. realloc не реагирует на конструкторы. Да плюс к тому new выделяет свободную память, а realloc/malloc/calloc выделяют память в куче.
1
oxotnik
1590 / 1067 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
20.05.2011, 14:09 #3
Цитата Сообщение от ForEveR Посмотреть сообщение
Да плюс к тому new выделяет свободную память, а realloc/malloc/calloc выделяют память в куче.
Как это понять?
new изнутри это тот же malloc плюс вызов конструктора
1
Evg
Эксперт CАвтор FAQ
17946 / 6177 / 412
Регистрация: 30.03.2009
Сообщений: 16,970
Записей в блоге: 27
20.05.2011, 14:27 #4
Цитата Сообщение от pito211 Посмотреть сообщение
мне препод сказал, что можно выделить память оператором new, а потом довыделить её с помощью realloc
Нельзя вперемешку использовать new/delete и malloc/realloc/free. Точнее можно, но с непредсказуемыми последствиями. В Си++ нет встроенной конструкции для перевыделения памяти, а потому такое делается через malloc/realloc. Если препод бестолковый из разряда "у меня работает, значит можно", то сделай new/realloc, но для себя надо понимать, что это интерфейсы разных уровней, которые в общем случае не следует перемешивать

Добавлено через 2 минуты
Цитата Сообщение от oxotnik Посмотреть сообщение
new изнутри это тот же malloc плюс вызов конструктора
На самом деле вызов конструктора - это снаружи new, а не изнутри (т.е. вызов конструктора ставит компилятор, а не реализация оператора new). По поводу того, что "это тот же malloc" - это постфактум в реализациях. Но, как мне кажется, никто не гарантирует, что new это в чистом виде обёртка вокруг malloc'а и что там никаких дополнительных действий не делается
1
oxotnik
1590 / 1067 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
20.05.2011, 14:41 #5
Цитата Сообщение от Evg Посмотреть сообщение
Если препод бестолковый из разряда "у меня работает, значит можно"
Препод как раз толковый. Думаю тут задача стоит изучить "изнутри" оператор new как он работает.
А по теме: для своего класса надо переопределить new.

Добавлено через 12 минут
Цитата Сообщение от Evg Посмотреть сообщение
На самом деле вызов конструктора - это снаружи new
да с вызовом конструктора внутри погорячился... ибо на стеке нет никакого new но конструктор вызывается, следовательно new тут не причем

Цитата Сообщение от Evg Посмотреть сообщение
что new это в чистом виде обёртка вокруг malloc'а и что там никаких дополнительных действий не делается
ну еще проверки и вызов исключения если нехватает памяти:
Код
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
ForEveR
В астрале
Эксперт С++
7978 / 4737 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
20.05.2011, 15:00 #6
oxotnik, Ну одна из реализаций. Кто сказал что она единственная?

Добавлено через 4 минуты
Тем более что реализовать что-то вроде realloc средствами С++ ну вообще не проблема. Правда он будет не оптимизированный да и вообще, но все же.
1
pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
20.05.2011, 15:16  [ТС] #7
вы уже чё то не то обсуждаете

лучше расскажите как
Цитата Сообщение от ForEveR Посмотреть сообщение
[b]
реализовать что-то вроде realloc средствами С++
без кода, в общих чертах, если не затруднит
0
Evg
Эксперт CАвтор FAQ
17946 / 6177 / 412
Регистрация: 30.03.2009
Сообщений: 16,970
Записей в блоге: 27
20.05.2011, 15:23 #8
Цитата Сообщение от oxotnik Посмотреть сообщение
Препод как раз толковый. Думаю тут задача стоит изучить "изнутри" оператор new как он работает.
А по теме: для своего класса надо переопределить new.
В первом посте написано: "препод сказал, что можно выделить память оператором new, а потом довыделить её с помощью realloc", а в задании про переопределение оператора new ничегоне сказано. Так что хз что тут: либо препод неправильный, либо автор слова препода исковеркал

Цитата Сообщение от oxotnik Посмотреть сообщение
ну еще проверки и вызов исключения если нехватает памяти
Проверки фиг с ними. Я имел в виду то, что new по аналогии с malloc'ом ожет выделять чуть больше памяти, чтобы хранить воспомогательную информацию и при этом возвращать немного не то, что вернул malloc. В этом отношении при комбинации new/realloc можно конкретно накосячить

Цитата Сообщение от ForEveR Посмотреть сообщение
Тем более что реализовать что-то вроде realloc средствами С++ ну вообще не проблема
В одной из тем обсуждали, что встроенных аналогов realloc'а нет, только всякие контейнеры типа std::vector (которые по сути обёртки над malloc/realloc)
1
oxotnik
1590 / 1067 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
20.05.2011, 15:30 #9
Цитата Сообщение от Evg Посмотреть сообщение
Я имел в виду то, что new по аналогии с malloc'ом ожет выделять чуть больше памяти, чтобы хранить воспомогательную информацию и при этом возвращать немного не то, что вернул malloc. В этом отношении при комбинации new/realloc можно конкретно накосячить
Посмотрел реализацию gcc Студии, борланда, везде практически одно и тоже.
Выделяется память через malloc делаются проверки, и указатель возвращается.
Под какую такую информацию надо резервировать доп. память?
А что тогда sizeof будет показывать?
0
Evg
Эксперт CАвтор FAQ
17946 / 6177 / 412
Регистрация: 30.03.2009
Сообщений: 16,970
Записей в блоге: 27
20.05.2011, 15:45 #10
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от oxotnik Посмотреть сообщение
Под какую такую информацию надо резервировать доп. память?
А что тогда sizeof будет показывать?
glibc'шная реализация malloc'f при каждом обращении выделяет памяти больше, чем нужно. И в дополнительную память кладёт магическое число, чтобы делать контроль внутри realloc'а и free. Схематично что-то типа того:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void*
malloc (long size)
{
  char *p;
 
  /* Функцию, которая по-настоящему выделяет память, условно назвал get_mem.
   * В реальности там всё куда сложнее, я просто хочу пояснить принцип
   * Здесь мы выделили дополнительный фрагмент памяти */
  p = get_mem (sizeof (long) + size);
 
  /* В начало реально выделенной памяти кладём магическое число */
  *((long*)p) = 0xdeadbeef;
 
  /* Наружу отдаём память, лежащую за магическим числом */
  return p + sizeof (long);
}
 
void free (void *ptr)
{
  char *p;
 
  /* Наружу мы отдавали результат get_mem со сдвигом. Теперь вернём значение
   * обратно, получив таким образом то, что реально выдал get_mem */
  p = ptr - sizeof (long);
 
  if (*((long*)p) != 0xdeadbeef)
  {
    /* АХТУНГ! Магическое число не совпадает. Вероятнее всего в free подали
     * совсем не то, что вернул malloc */
  }
 
  /* Название функции free_mem условное */
  free_mem (p);
}
Пи таком построении всё читерство с магическими числами сосредоточено внутри интерфейсов malloc и free и для пользователя оно всё прозрачно. Т.е. пользовтатель получил указатель, который вернул malloc, а затем отдал этот указатель в free. То, что это не есть результат настоящего выделения памяти, а результат со сдвигом, снаружи никак не проявляется.

Ровно таким же образом могут быть реализованы операторы new и delete. Т.е. new внутри себя использует malloc, но наружу может отдать немного не то, что вернул malloc

Пример, как это работает в glibc под linux'ом:

C
1
2
3
4
5
6
7
8
9
10
11
#include <stdlib.h>
 
int main (void)
{
  int *p;
  
  p = malloc (100);
  /* Некорректный вызов free */
  free (p + 10);
  return 0;
}
На исполнении видим, что сработал Ахтунг

Код
$ gcc t.c
$ ./a.out
*** glibc detected *** ./a.out: free(): invalid pointer: 0x0804b030 ***
Aborted
6
oxotnik
1590 / 1067 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
20.05.2011, 15:55 #11
Evg, а где тогда хранится размер выделяемой памяти, что бы free(*p) правильно сработал?
1
Evg
Эксперт CАвтор FAQ
17946 / 6177 / 412
Регистрация: 30.03.2009
Сообщений: 16,970
Записей в блоге: 27
20.05.2011, 16:01 #12
Цитата Сообщение от oxotnik Посмотреть сообщение
Evg, а где тогда хранится размер выделяемой памяти, что бы free(*p) правильно сработал?
Например, там же, где и магическое число. Это всё зависит от реализации malloc'а. Реально malloc внутри себя выделяет память с точностью до страницы (чтобы при куче маленьких выделений памяти поменьше обращаться к системе). Там ещё целая куча всяких наноалгоритмов

Вот, например, одна из реализаций malloc'а: тыц

Добавлено через 35 секунд
Цитата Сообщение от oxotnik Посмотреть сообщение
А что тогда sizeof будет показывать?
sizeof от чего?
1
oxotnik
1590 / 1067 / 33
Регистрация: 21.08.2008
Сообщений: 4,545
Записей в блоге: 1
20.05.2011, 16:09 #13
Цитата Сообщение от Evg Посмотреть сообщение
sizeof от чего?
вопрос снимается...
ЗЫ: помогли называется пацану... (ТС который)
1
pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
20.05.2011, 16:15  [ТС] #14
спасибо всем за развёрнутый ответ
0
ForEveR
В астрале
Эксперт С++
7978 / 4737 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
20.05.2011, 16:24 #15
pito211, Да элементарно. Подход как у вектора.
Используем себе массив - нужно больше - вызываем специальную самописную функцию, перераспределяющую память, путем создания нового указателя (с большим размером выделенной памяти) и копирования туда элементов, удалением старого указателя и присваиванием старому указателю адрес нового, изменение переменной размера для старого.
Ну и собственно-то все.
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.05.2011, 16:24
Привет! Вот еще темы с ответами:

Запутался с malloc и realloc - C++ Builder
Добрый день. Не могу понять какой размер нужно выделить для массива указателей на указатели. Какого размера должен быть указатель на на...

Строка символов и функция realloc - C++ Builder
Вот, есть программа на Си, в которой вызывается функция realloc, после чего всё вылетает и закрывается (вложение - весь код, строка № 56): ...

Вызов конструктора из конструктора и проверка правильности передаваемых параметров - C#
Существует такой код: public Matrix(Double array) : this(array.GetLength(0), array.GetLength(1)) { ...

Вызов конструктора из конструктора - ошибка - C#
Айм водеринг. Но разве из одного конструктора нельзя вызвать другой (из StadoOvechek() вызвать StadoOvechek(int countOvechkas) ) ? Вот...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
20.05.2011, 16:24
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru