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

Динамическое выделение памяти - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.75
bgm313
12 / 12 / 2
Регистрация: 27.07.2012
Сообщений: 208
28.08.2012, 14:49     Динамическое выделение памяти #1
Пусть есть класс с полем char *p. Если для поля p выделяется память динамически, как для массива и для самих объектов память выделяется тоже динамически в main. То где ловить исключения, которые могут быть связаны с выделением памяти: и в конструкторах и в основной программе или только в основной программе, а в конструкторах выбрасывать соотв.исключения?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
28.08.2012, 15:00     Динамическое выделение памяти #2
все зависит от целей вылавливания исключения.

вот код:
Foo* p = new Foo();

тут сперва выделяется память под объект типа Foo. Если не получилось, то летит исключение и до конструктора Foo дело не доходит. Если же все хорошо, то в выделеной памяти начинает конструироваться объект. В общем вызывается конструктор Foo. Внутри конструктора выполняется код, который бросает исключение (в том числе может бросится исключение о неудачном выделении памяти или хз что еще. все зависит от того, что именно происходит в конструкторе). Если это исключение покидает конструктор, то объект не создан до конца и деструктор для него не зовется. Эту ситуацию отлавливает код оператора new, освобождает выделенную память и пробрасывает исключение дальше. Если же икслючение ловится в теле конструктора и не копидает его, то объект вроде как сконструируется. Возможно у него будет невалидное состояние с точки зрения полозователей такого класса, но тем не менее это будет полностью сконструированный объект.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
28.08.2012, 15:02     Динамическое выделение памяти #3
Это в большей степени зависит от логики самого конструктора. Если там можно продолжить создание объекта, несмотря на невозможность выделения памяти, то можно перехватить. Если требуется выполнить какие-то действия, связанные с неудачным выделением, то тоже придётся перехватывать (в конструкторе). Но в большинстве случаев можно в конструкторе ничего не делать, а обрабатывать в вызывающей функции или дальше.
Стоит рассмотреть, кстати, возможность замены int* на std::vector<int>. Если по-каким-то причинам это нежелательно, то следующие кандидаты на рассмотрение std::auto_ptr<int> и std::shared_ptr<int> (последний только для C++11, но есть аналог в boost).
bgm313
12 / 12 / 2
Регистрация: 27.07.2012
Сообщений: 208
28.08.2012, 15:15  [ТС]     Динамическое выделение памяти #4
Скажите, а как можно сделать так, чтобы при вызове конструктор и при неудачном выделение памяти для поля в конструкторе, происходил откат, т.е. объект разрушался. Может быть вызвать деструктор из конструктора?
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
28.08.2012, 15:20     Динамическое выделение памяти #5
Всё, что успело "сконструироваться" до возникновения исключения будет разрушено автоматически (главное, чтобы это исклчение хоть где-то в программе перехватывалось). Деструктор явно вызывать нельзя, так как созданные объекты будут разрушаться дважды, и даже созданные один раз тоже будут разрушаться. Так что либо не обрабатывать исключение в конструкторе, либо обработав прокинуть его дальше (это если надо разрушить объект).
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
28.08.2012, 15:21     Динамическое выделение памяти #6
Ловить в конструкторе; удалять (тоже в конструкторе) всё, что построили до этого (но не более), и бросать дальше.

Не надо грузить вышележащий код, который вызвал этот самый конструктор Object, своими микропроблемами: "аааа, Object не может выделить память для своего третьего сверху приватного поля". Ему важна макропроблема: у него Object не создался. Что он будет делать, когда словит такое исключение? Объект инициализирован криво, так что деструктор может только усугубить ситуацию. Узнать и починить проблему внутри Object внешний код тоже не может. Так что уж лучше, когда Object() сам уберёт за собой и скажет наверх: "Мама, я облажался, но всё прибрал, можно сделать ещё попытку".
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
28.08.2012, 15:23     Динамическое выделение памяти #7
никак. деструктор нельзя звать для неполностью сконструированного объекта.
откат делается за счет идиомы RAII (Resource allocation is initialization). Как уже сказали, мемберы, для которых выделяется память лучше заворачивать в смарт поинтеры. В этом случае все отработает как надо:

C++
1
2
3
4
5
6
7
8
9
10
11
12
class Foo
{
   std::auto_ptr<int> m_ptr1;
   std::auto_ptr<int> m_ptr2;
 
public:
   Foo()
     : m_ptr1(new int(1))
     , m_ptr2(new int(2)) // вот тут летит исключение
   {
   }
};
В такой ситуации объект m_ptr1 будет полностью сконструирован, а m_ptr2 - нет. Т.к. деструкторы зовутся для полностью сконструированных объектов а m_ptr1 - как раз такой объект, а не голый указатель, для него деструктор позовется несмотря на то, что деструктор класса Foo вызван не будет. Деструктор auto_ptr<T> как раз позовет delete для указателя, который хранится в этом смарт-поинтере
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.08.2012, 15:23     Динамическое выделение памяти
Еще ссылки по теме:

Динамическое выделение памяти C++
C++ Динамическое выделение памяти

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

Или воспользуйтесь поиском по форуму:
-=ЮрА=-
Заблокирован
Автор FAQ
28.08.2012, 15:23     Динамическое выделение памяти #8
bgm313, исключения с выделением памяти - это bad_alloc делай вот такую обвёртку
C++
1
2
3
4
5
6
7
8
try
{
    int *ptr = new int[N];
}
catch(bad_alloc &e)
{
    cerr<<e.what()<<endl;
}
Yandex
Объявления
28.08.2012, 15:23     Динамическое выделение памяти
Ответ Создать тему
Опции темы

Текущее время: 23:27. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru