Чем больше Я читаю Что касается RAII, я понимаю, что использование стека — это способ убедиться, что код безопасен для исключений.
Означает ли это каждый раз, когда я делаю new()
в моем коде я делаю что-то не так в том смысле, что есть лучший способ сделать это, используя принцип RAII?
Вы не обязательно делать что-то не так, если вы используете new
, но стоит проверить, что вы все делаете правильно.
new
выражение должно быть немедленно помещено под контроль умного указателя, обычно передавая его прямо в конструктор.shared_ptr
тогда вы наверное делать неправильно. Вы, вероятно, должны использовать make_shared
вместо. Есть некоторые ситуации, когда вы не должны (использование weak_ptr
на большие объекты), а некоторые, где вы не можете (C ++ 03 без Boost).delete
тогда вы в значительной степени делаете это неправильно, если вы не пишете свой собственный класс интеллектуальных указателей. И даже в этом случае ваш умный указатель может использовать другой умный указатель для сохранения работы.new
исключительно потому, что объект «слишком большой для стека», подумайте о написании класса, который действует как дескриптор объекта, используя unique_ptr
или же scoped_ptr
управлять им, чтобы с точки зрения пользователя объекты, с которыми он имеет дело, были автоматическими переменными. Если вам это нравится, вы можете расширить его до полной идиомы. Даже если вам не нужен другой класс, рассмотрите функцию, которая создает объект и возвращает unique_ptr
к нему, который вы можете затем назвать как auto foohandle = give_me_a_foo();
, затем give_me_a_foo
содержит new
, но другой пользовательский код этого не делает, и вы поощряете практику автоматического добавления объектов в объекты RAII.Существуют альтернативные стратегии управления ресурсами для RAII в C ++, но вы бы знали об этом, если бы использовали их, и это могло бы повлиять на то, что считается «неправильным».
Я думаю, что вы не до конца поняли, что на самом деле означает RAII. Динамическое распределение, точно так же, как другие программы, такие как файлы, подключения к базам данных и т. Д., Необходимы в программах. RAII фокусируется на том, как управлять этими ресурсами, и способ состоит в том, чтобы ресурсы управлялись объектами с автоматической продолжительностью хранения (либо в стеке, либо в качестве члена другого объекта).
Это не означает, что каждый ресурс должен быть выделен в стеке, но скорее, если вы выделяете что-то в куче, вы должны делегировать ответственность за управление этой памятью объекту, который находится в стеке.
Не за что. Если природа зверя (требования к распределению) действительно динамична, то в конечном итоге он будет либо возникать из кучи, либо из-за серьезного обмана указателя стека.
Лучшее, что вы можете сделать, — это использовать обертки, которые вам подходят. (Я могу сказать вам, как часто я использую std :: vector<> когда мне нужен динамический временный буфер, защищенный областью видимости). Это одна из самых идеальных причин для использования хорошо поддерживаемых и разработанных библиотек, таких как STL и т. Д. И в отличие от C # или Java, его предсказуемость, которая имеет огромное значение, когда действительно необходимо.
Нет, пространство стека очень ограничено, поэтому вы не хотите помещать на него огромные вещи, отсюда и термин переполнение стека. Также, если вам нужно, чтобы срок жизни объекта был больше, чем у вашей функции, вы не можете поместить его в стек.