Правило 17: Помещение в «интеллектуальный» указатель объекта, вьщеленного с помощью new, лучше располагать в отдельном предложении
Правило 17: Помещение в «интеллектуальный» указатель объекта, вьщеленного с помощью new, лучше располагать в отдельном предложении
Предположим, что есть функция, возвращающая уровень приоритета обработки, и другая функция для выполнения некоторой обработки динамически выделенного объекта Widget в соответствии с этим приоритетом:
int priority();
void processWidgets(std::tr1::shared_ptr<Widget> pw, int priority);
Помня о премудростях применения объектов, управляющих ресурсами (см. правило 13), processWidgets использует «интеллектуальный» указатель (здесь – tr1::shared_ptr) для обработки динамически выделенного объекта. Рассмотрим теперь такой вызов processWidgets:
processWidgets(new Widget, priority());
Стоп, не надо его рассматривать! Он не скомпилируется. Конструктор tr1::shared_ptr, принимающий указатель, объявлен с ключевым словом explicit, поэтому не происходит неявного преобразования из типа указателя, возвращенного выражением «new Widget», в тип tr1::shared_ptr, которого ожидает функция process-Widgets. Однако следующий код компилируется:
processWidgets(std::tr1::shared_ptr<Widget>(new Widget), priority());
Как это ни странно, но несмотря на использование управляющего ресурсами объекта, здесь возможна утечка ресурсов. Разберемся, почему.
Прежде чем компилятор сможет сгенерировать вызов processWidgets, он должен вычислить аргументы, переданные ему в качестве параметров. Второй аргумент – просто вызов функции priority, но первый – (std::tr1::shared_ptr<Widget> (new Widget)) – состоит из двух частей:
• выполнение выражения «new Widget»;
• вызов конструктора tr1::shared_ptr.
Перед тем как произойдет вызов processWidgets, компилятор должен сгенерировать код для решения следующих трех задач:
• вызов priority;
• выполнение «new Widget»;
• вызов конструктора tr1::shared_ptr.
Компиляторам C++ предоставлена определенная свобода в определении порядка выполнения этих операций. (И этим C++ отличается от таких языков, как Java и C#, где параметры функций всегда вычисляются в определенном порядке.) Выражение «new Widget» должно быть выполнено перед вызовом конструктора tr1::shared_ptr, потому что результат этого выражения передается конструктору в качестве аргумента, однако вызов priority может быть выполнен первым, вторым или третьим. Если компилятор решит поставить его на второе место (иногда это позволяет сгенерировать более эффективный код), то мы получим следующую последовательность операций:
1. Выполнение «new Widget».
2. Вызов priority.
3. Вызов конструктора tr1::shared_ptr.
Посмотрим, что случится, если вызов priority возбудит исключение. В этом случае указатель, возвращенный «new Widget», будет потерян, то есть не помещен в объект tr1::shared_ptr, который, как ожидается, должен предотвратить утечку ресурса. Утечка при вызове processWidgets происходит из-за того, что исключение возникает между моментом создания ресурса и моментом помещения его в управляющий объект.
Избежать подобной проблемы просто: используйте отдельные предложения для создания объекта Widget и помещения его в интеллектуальный указатель, а затем передайте этот интеллектуальный указатель processWidgets:
std::tr1::shared_ptr<Widget> pw(new Widget); // поместить новый объект
// в интеллектуальный указатель
// в отдельном предложении
processWidget(pw, priority()); // этот вызов не приведет
// к утечке
Такой способ работает потому, что компиляторам предоставляется меньше свободы в переопределении порядка операций в разных предложениях, чем в одном. В модифицированном коде выражение «new Widget» и вызов конструктора tr1::shared_ptr отделены от вызова priority, поэтому компилятор не может вставить вызов priority между ними.
Что следует помнить
• Помещайте объекты, выделенные оператором new, в «интеллектуальные» указатели в отдельном предложении. В противном случае такие вызовы могут привести к утечкам ресурсов, если возникнет исключение.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Помещение значка статуса на веб-страницу
Помещение значка статуса на веб-страницу В качестве бонуса ко всем замечательным возможностям Skype у вас есть еще одна – отображение на веб-странице пользователя его статуса в Skype с помощью специальной кнопки (значка). Это значит, что любой человек, зашедший на вашу
Операторы, используемые в предложении WHERE
Операторы, используемые в предложении WHERE При построении предложения WHERE можно использовать операторы, перечисленные в табл. 2.1.Таблица 2.1. операторы, используемые в предложении WHERE Оператор Функция < Меньше <= Меньше или равно > Больше >= Больше или равно =
Установка свойств объекта с помощью процедур Property Let
Установка свойств объекта с помощью процедур Property Let Процедура Property Let устанавливает значение свойства. В своей простейшей форме процедура Property Let берет переданное ей в виде аргумента значение и присваивает его переменной, представляющей свойство. В предыдущем примере
Чтение свойств объекта с помощью процедур Property Get
Чтение свойств объекта с помощью процедур Property Get Процедура Property Get подобна процедуре типа Function в том смысле, что она возвращает значение - конечно же, значение свойства, Как и в случае процедуры типа Function, значение, которое должно быть возвращено, присваивается имени
Помещение элемента управления в панель Toolbox
Помещение элемента управления в панель Toolbox Зарегистрировав новый элемент управления, активизируйте его, поместив элемент управления в панель элементов управления (Toolbox). Вот как это сделать.1. Активизируйте любое окно UserForm в редакторе Visual Basic, чтобы на экране появилась
1.6.2. Правило ясности: ясность лучше, чем мастерство
1.6.2. Правило ясности: ясность лучше, чем мастерство Поскольку обслуживание является важным и дорогостоящим, следует писать такие программы, как если бы обмен наиболее важной информацией, осуществляемый программой, был связан не с компьютером, выполняющим данную
Правило 12: Копируйте все части объекта
Правило 12: Копируйте все части объекта В хорошо спроектированных объектно-ориентированных системах, которые инкапсулируют внутреннее устройство объектов, копированием занимаются только две функции: конструктор копирования и оператор присваивания. Назовем их
Правило 38: Моделируйте отношение «содержит» или «реализуется посредством» с помощью композиции
Правило 38: Моделируйте отношение «содержит» или «реализуется посредством» с помощью композиции Композиция – это отношение между типами, которое возникает тогда, когда объект одного типа содержит в себе объекты других типов. Например:class Address {...}; // адрес проживанияclass
1.6.2. Правило ясности: ясность лучше, чем мастерство
1.6.2. Правило ясности: ясность лучше, чем мастерство Поскольку обслуживание является важным и дорогостоящим, следует писать такие программы, как если бы обмен наиболее важной информацией, осуществляемый программой, был связан не с компьютером, выполняющим данную
Помещение файла в документ
Помещение файла в документ При работе с открытым документом мы можем добавить в него другой документ, создав для него новый слой (см. главу 10). Эта операция выполняется немного по-разному для растровых и векторных документов. Растровые документы можно просто
Обновление базы данных с помощью объекта адаптера данных
Обновление базы данных с помощью объекта адаптера данных Адаптеры данных могут не только заполнять для вас таблицы объекта DataSet. Они могут также поддерживать набор объектов основных SQL-команд, используя их для возвращения модифицированных данных обратно в хранилище
Помещение изображения в ячейку StringGrid
Помещение изображения в ячейку StringGrid Возможно ли поместить изображение в одну из ячеек компонента StringGrid?Такое позволяет обработчик события OnDrawCell. Приводим скелет кода, демонстрирующий принцип вывода изображения в ячейке компонента:with StringGrid1.Canvas do begin {…} Draw(Rect.Left, Rect.Top,
ОГОРОД КОЗЛОВСКОГО: Heavy metal, или Лучше меньше, да лучше
ОГОРОД КОЗЛОВСКОГО: Heavy metal, или Лучше меньше, да лучше Автор: Козловский ЕвгенийНа Новый год, в числе прочего, получился новенький фотоаппарат от Casio: EX S770. Последняя на тот момент и безусловно лучшая модель! Совершенная в своем роде. Таким образом, смутная мечта всегда
Интеллектуальный эквалайзер FreeFilter
Интеллектуальный эквалайзер FreeFilter Производитель: Steinberg.Предполагает установленный DirectX.FreeFilter не имеет аналогов среди продукции других конкурирующих фирм. Это высококачественный линейный и логарифмический эквалайзер со множеством свойств, необычных для такого класса