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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.73
ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
#1

Стратегия "получение ресурса есть инициализация" - C++

14.04.2013, 11:21. Просмотров 1338. Ответов 29
Метки нет (Все метки)

Здорова!
Тут вообщем новую концепцию ООП вычитал "получение ресурса есть инициализация"
Вообщем считается когда используешь исключения, то обязательно нужно соблюдать эту концепцию?
И еще считается, что этот способ очень хороший для работы с умными указателями, но как его можно применить к умным указателям?
Класс умный указатель этож как бы оболочка он токо ссылки содержит, какой там может быть ресурс, какое там освобождение, если он и так ресурсов не содержит????
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.04.2013, 11:21     Стратегия "получение ресурса есть инициализация"
Посмотрите здесь:

Если в строке есть хоть один ноль - вывести в файл output.txt "YES", иначе вывести "NO"; C++
C++ Что делать с ошибкой: C2440: инициализация: невозможно преобразовать "int **" в "int *"
C++ Модель распределения памяти разделами переменного размера с общей очередью, стратегия "наименее подходящий"
Как сделать, так чтобы i и j можно было вводить самому "i" И "j" в цикле, есть программа C++
C++ Заданный словарь слов. Найти в нем слова-палиндромы, то есть такие, которые одинаково читаются слева направо и наоборот, например, "АННА", "ШАЛАШ"
C++ Дана строка, в котором есть слово "да" или слово "нет". Если в нем есть слово "нет", то удалить его
Warning C4244: инициализация: преобразование "__int64" в "int", возможна потеря данных C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
OhMyGodSoLong
~ Эврика! ~
1243 / 992 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
14.04.2013, 11:23     Стратегия "получение ресурса есть инициализация" #2
Ресурс — владение указателем. Владение — это обязанность вызвать деструктор объекта, на который указывает этот указатель.
ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
14.04.2013, 11:27  [ТС]     Стратегия "получение ресурса есть инициализация" #3
Цитата Сообщение от OhMyGodSoLong Посмотреть сообщение
Ресурс — владение указателем. Владение — это обязанность вызвать деструктор объекта, на который указывает этот указатель.
А от если у меня есть такой класс который просто тупо как бы ссылки содержит, то что я должен в деструкторе вызвать?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Ptr
{
    int* p;//ykazatel6 na tekychii element
    int* array;//ykazatel6 na macciv
    int size;//razmer macciva
    
public:
    class Run_time_error {};
    //konctryktor preobrazovani9
    Ptr_to_T(int*p, int* v, int s)//priv9zka k maccivy v razmera s; nach. znachenie p
    :p(p),array(v),size(s){}
    
    ~Ptr_to_T(){};
};
Я ж оператор new здесь не вызываю вроде, ток что мне тогда освобождать?
Я вообще считаю если new вызывается тогда токо можно что то освободить вызвал delete. А в случае с классом выше как быть? Или мне нужно вызвать new обязательно? хз. как делать.
OhMyGodSoLong
~ Эврика! ~
1243 / 992 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
14.04.2013, 11:39     Стратегия "получение ресурса есть инициализация" #4
А вот именно это и есть понятие владения.

Класс Ptr обладает ссылками на объекты, но не обязан их удалять. То есть он не контролирует их время жизни, не владеет ими. Он просто получил указатели на какие-то объекты, созданные ранее.

Соответственно, возникает проблема: эти объекты нельзя удалить, пока они нужны Ptr. Для её решения можно поступить двумя путями: или передавать Ptr владение над этими объектами, или разделить владение между несколькими объектами. Для первого случая есть std::unique_ptr — при его передаче предыдущий владелец теряет ссылки на эти объекты, а вместе с ними и обязательство удалять объекты, тогда как Ptr всё это получает. Для второго случая есть std::shared_ptr — тогда оба объекта (и предыдущий владелец, и этот Ptr) совместно владеют одним объектом, удалять этот объект будет тот, кто останется последним.
ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
14.04.2013, 11:48  [ТС]     Стратегия "получение ресурса есть инициализация" #5
Не знаю даже как это от если у меня массив будет int v[200], То я просто инициализирую Ptr
Ptr b(v[0],v,200); Я ж наверно не смогу в деструкторе удалить этот объект никак, да мне даже вызывать его смысла нету (да и не зачем), ведь там же храниться будет не копия ресурсов, а ссылки на эти ресурсы, значит смысл удалять (освобождать)? В данном случае наверно нету смысла, если б копия, а это наверно пришлось бы хапать новую область памяти и туда просто перекопировать значение тогда да нужно было б высвободить память. Ну правильно ж? Скажи, что мне деструктор в классе можно и не определять?

Да вообще проще считать, что деструктор это как очиститель, то есть удаляет данные токо те которые как бы загватил класс, к левым данным напимер ссылки смысла нету лезть. Так будет впринципе правильно.

Да и вообще скорее всего ссылки это не ресурс, ресурс это память.
DU
1480 / 1056 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
14.04.2013, 12:21     Стратегия "получение ресурса есть инициализация" #6
Ресурсы - это не только память.
Если вы открыли файл, вам нужно его закрыть.
Если вы захватили мьютекс, вам нужно будет его освободить.
Если перед началом работы с каким-то объектом нужно его залочить, увеличить счетчик пользователей, вызвать еще-что-нибудь специфической, а по завершении - разлочить, уменьшить или еще что-то - то тут тоже это все лучше делать специальными объектами, которые в конструкторе выполняют "захват", а в деструкторе - "освобождение".
ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
14.04.2013, 12:34  [ТС]     Стратегия "получение ресурса есть инициализация" #7
DU, Ну правильно будет скорее всего в классе в то в котором захвачен ресурс в нем и освобождать его, в любом случае деструктор объекта раньше времени не вызовется пока этот объект используется. Да если этот объект будет использоваться в каком нибудь левом классе как бы указателем на этот объект это будет тоже считаться, что объект используется. Сразу трудно понять эту фигню.
TheChosenOne
13 / 13 / 1
Регистрация: 13.09.2013
Сообщений: 113
26.06.2014, 19:34     Стратегия "получение ресурса есть инициализация" #8
Хотелось бы поднять тему и задать такой вопрос : RAII - это не панацея ведь ?
Например есть класс,задача которого владеть памятью. В его конструкторе есть строчка int* p = new int[x];После того как выполнилась эта строчка генерируется исключение. Получается, что деструктор класса не будет вызван,память,которая была выделена - не будет возвращена. Т.е. если объект не удалось полностью сконструировать,а один и ресурсов будет уже захвачен (в нашем случае память) , то на корректное освобождение этого ресурса надеется не стоит ?
Croessmah
Модератор
Эксперт CЭксперт С++
12675 / 7183 / 801
Регистрация: 27.09.2012
Сообщений: 17,709
Записей в блоге: 2
Завершенные тесты: 1
26.06.2014, 20:33     Стратегия "получение ресурса есть инициализация" #9
Цитата Сообщение от TheChosenOne Посмотреть сообщение
то на корректное освобождение этого ресурса надеется не стоит ?
конечно нет. И это касается не только конструкторов классов.
0x10
2452 / 1624 / 238
Регистрация: 24.11.2012
Сообщений: 3,999
26.06.2014, 20:36     Стратегия "получение ресурса есть инициализация" #10
TheChosenOne, мораль - пишите такие конструкторы, которые не кидают исключений после захвата ресурса.
TheChosenOne
13 / 13 / 1
Регистрация: 13.09.2013
Сообщений: 113
26.06.2014, 20:51     Стратегия "получение ресурса есть инициализация" #11
Croessmah, ну сам принцип RAII наталкивает меня на то,что если в конструкторе будет брошено исключение,то вся стратегия полетит...ммм... в космос
0x10, а как мне написать класс,который будет захватывать память и при этом будет корректно ее освобождать в случае если не удалось захватить весь ее объем( например мне нужна память для одного числа int и одного числа double ) ? Что делать если мне удалось получить память для int,а вот для double не хватило ?
Croessmah
Модератор
Эксперт CЭксперт С++
12675 / 7183 / 801
Регистрация: 27.09.2012
Сообщений: 17,709
Записей в блоге: 2
Завершенные тесты: 1
26.06.2014, 21:08     Стратегия "получение ресурса есть инициализация" #12
Цитата Сообщение от TheChosenOne Посмотреть сообщение
Что делать если мне удалось получить память для int,а вот для double не хватило ?
умные указатели. Всё уже давно реализованно
0x10
2452 / 1624 / 238
Регистрация: 24.11.2012
Сообщений: 3,999
26.06.2014, 21:12     Стратегия "получение ресурса есть инициализация" #13
Цитата Сообщение от TheChosenOne Посмотреть сообщение
а как мне написать класс,который будет захватывать память и при этом будет корректно ее освобождать в случае если не удалось захватить весь ее объем
Каждая аллокация памяти - захват отдельного ресурса. Про умные указатели сказали выше.
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
26.06.2014, 23:07     Стратегия "получение ресурса есть инициализация" #14
Цитата Сообщение от TheChosenOne Посмотреть сообщение
то вся стратегия полетит...ммм... в космос
Ничего никуда не летит. Просто правильное применение предполагает последовательность. Т.е. если используешь эту идиому - использовать ее нужно везде.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class A
{
public:
    A() 
        : a_(new int[2]) // RAII
    {
         throw std::logic_error("catch this"); // исключение, 
                                               // но деструктор уже созданных объектов гарантированно 
                                               // вызовется при этом. В итоге, благодаря RAII, a_ освободит память.
    }
private:
    std::unique_ptr<int[]> a_;
};
Croessmah
Модератор
Эксперт CЭксперт С++
12675 / 7183 / 801
Регистрация: 27.09.2012
Сообщений: 17,709
Записей в блоге: 2
Завершенные тесты: 1
26.06.2014, 23:11     Стратегия "получение ресурса есть инициализация" #15
Цитата Сообщение от DrOffset Посмотреть сообщение
Т.е. если используешь эту идиому - использовать ее нужно везде.
думаю, имеется ввиду что если в конструкторе a_ вылетит исключение, но такие классы проектируются так, чтобы этого не случилось.
Tulosba
:)
Эксперт С++
4387 / 3230 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
27.06.2014, 10:33     Стратегия "получение ресурса есть инициализация" #16
Цитата Сообщение от TheChosenOne Посмотреть сообщение
В его конструкторе есть строчка int* p = new int[x];После того как выполнилась эта строчка генерируется исключение.
Следовательно надо сделать так, чтобы за выделение памяти отвечал отдельный объект, т.е. вместо int* заведите например std::vector<int>.
TheChosenOne
13 / 13 / 1
Регистрация: 13.09.2013
Сообщений: 113
28.06.2014, 00:41     Стратегия "получение ресурса есть инициализация" #17
Tulosba, да,я уже разобрался,спасибо

Добавлено через 1 час 16 минут
А вызов деструкторов для уже созданных объектов гарантирует реализация С++ или этот вызов как-то связан с областью видимости?Т.е. что вызывает деструктор ?

Добавлено через 25 минут
Интересно вот что : Если было брошено исключение,но нет его обработчика,объект конструируется,но не полностью... И существует в таком виде до конца области видимости... Т.е. если объект не удалось создать полностью ,то под-объекты которые были созданы продолжают существовать (вместе с не до конца созданным объектом). Но если вдруг есть обработчик ,тогда все норм. Ощущение что механизм раскрутки стека работает только когда есть обработчик... И подобъекты уничтожаются только когда находится обработчик,а не по мере раскрутки стека...

Добавлено через 30 минут
Упс,ошибочка вышла,terminate() вызывается,с последним разобрался...
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
28.06.2014, 00:58     Стратегия "получение ресурса есть инициализация" #18
Цитата Сообщение от TheChosenOne Посмотреть сообщение
Ощущение что механизм раскрутки стека работает только когда есть обработчик
Нет. Деструкторы вызываются при выходе из области видимости. Выход любым легальным способом, в том числе через исключение.
TheChosenOne
13 / 13 / 1
Регистрация: 13.09.2013
Сообщений: 113
28.06.2014, 01:40     Стратегия "получение ресурса есть инициализация" #19
DrOffset, Из какой области видимости выходят подобъекты ? Конструтора?Но они не являются локальными по отношению к конструктору. try блока ? Ну тогда должен вызываться деструктор всего объекта,а этого не может быть т.к. объект не был создан.

Добавлено через 9 минут
15.2/2
An object that is partially constructed or partially destroyed will have destructors executed for all of its
fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and
the destructor has not yet begun execution
Все что нашел в стандарте... Ничего про область видимости...

Добавлено через 12 минут
на SOF мне ответили что сам конструктор недоконструированного объекта вызывает деструкторы подобъектов..Может кто-нибудь скажет что-то еще на этот счет ?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.06.2014, 02:09     Стратегия "получение ресурса есть инициализация"
Еще ссылки по теме:

C++ 0xC0000005: Нарушение прав доступа при записи "0xcccccccc". Инициализация строк
Для агрегатного объекта требуется инициализация с использованием "{.}" C++
C++ Инициализация массива: ошибка "array must be initialized with a brace-enclosed initializer"
Error C2440: инициализация: невозможно преобразовать "void *" в "listnode *". подскажите, что можно сделать? C++
C++ трудности с пониманием синтаксиса на примере реализации паттерна "стратегия"

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

Или воспользуйтесь поиском по форуму:
DrOffset
6840 / 4051 / 924
Регистрация: 30.01.2014
Сообщений: 6,855
28.06.2014, 02:09     Стратегия "получение ресурса есть инициализация" #20
Цитата Сообщение от TheChosenOne Посмотреть сообщение
try блока ? Ну тогда должен вызываться деструктор всего объекта,а этого не может быть т.к. объект не был создан.
Не try блока, а в том числе try блока. Той области видимости, где была попытка создания объекта (try-блок, функция, scope и т.п.). Уже созданные подобъекты принадлежат этой же области видимости, что и главный объект. Вот такой же код не вызывает вопросов?
C++
1
2
3
4
5
6
7
8
9
10
11
12
void foo()
{
    A a;
    B b; 
 
// throw и выход из области видимости    
    throw std::logic_error("");
         // вызов ~B()
         // вызов ~A()
    
    C c; // ~C() не вызывается 
}
Ситуация c подобъектами эквивалентна вышеописанной, представим что С у нас главный объект, а A и B - подобъекты.
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
class C
{
public:
    C() : a()
        , b() 
    {
        throw std::logic_error("");
    } 
 
private:
    A a;
    B b; 
}
 
// порядок создания тот же
void foo()
{
//  A a;
//  B b;
    C c; // throw и выход из области видимости 
         // вызов ~B()
         // вызов ~A()
         // ~C() не вызывается 
}
Yandex
Объявления
28.06.2014, 02:09     Стратегия "получение ресурса есть инициализация"
Ответ Создать тему
Опции темы

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