Чтение онлайн

на главную - закладки

Жанры

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

Наиболее часто используют возврат адреса нового объекта в куче или обновление адреса указателя, переданного как аргумент. Их реализация показана в примере 8.2, и она тривиальна и не требует дальнейших пояснений. Однако возврат из функции целого объекта используется реже — возможно, потому, что это требует больших накладных расходов.

При возврате временного объекта в стеке тела функции создается временный объект. При выходе из функции компилятор копирует данные из временного объекта в другой временный объект, который и возвращается из функции, Наконец, в вызывающей функции объекту с помощью оператора присвоения присваивается значение временного

объекта. Это означает, что на самом деле создается два объекта: объект в функции фабрики и временный объект, который возвращается из функции, содержимое которого затем копируется в целевой объект. Здесь осуществляется большое количество копирований (хотя компилятор может оптимизировать временный объект), так что при работе с большими объектами или частыми вызовами этой функции фабрики внимательно следите за тем, что в ней происходит.

Также эта методика копирования временных объектов работает только для объектов, которые ведут себя как объекты значений, что означает, что когда он копируется, то новая версия будет эквивалентна оригинальной. Для большинства объектов это выполняется, но для некоторых — нет. Например, рассмотрим создание объекта класса, прослушивающего сетевой порт. При создании экземпляра объекта он может начинать прослушивать целевой порт, так что скопировать его в новый объект не получится, так как при этом появятся два объекта, пытающиеся слушать один и тот же порт. В этом случае следует возвращать адрес объекта в куче.

Если вы пишете функцию или метод, создающий объекты, то посмотрите также рецепт 8.12. Используя шаблоны, функций можно написать одну функцию, которая будет возвращать новый объект любого типа. Например:

template<typename T>

T* createObject {

 return(new T);

}

MyClass* p1 = createObject;

MyOtherClass* p2 = createObject;

// ...

Этот подход удобен, если требуется единственная функция фабрики, которая сможет одинаковым образом создавать объекты любых классов (или группы связанных классов), что позволит избежать избыточного многократного кодирования функции фабрики.

Смотри также

Рецепт 8.12.

8.3. Использование конструкторов и деструкторов для управления ресурсами (RAII)

Проблема

Для класса, представляющего некоторый ресурс, требуется использовать конструктор для получения этого ресурса и деструктор для его освобождения. Эта методика часто называется «получение ресурсов как инициализация» (resource acquisition is initialization — RAII).

Решение

Выделите или получите ресурс в конструкторе и освободите этот ресурс в деструкторе. Это снизит объем кода, который пользователь класса должен будет написать для обработки исключений. Простая иллюстрация этой методики показана в примере 8.3.

Пример 8.3. Использование конструкторов и деструкторов

#include <iostream>

#include <string>

using namespace std;

class Socket {

public:

 Socket(const string& hostname) {}

};

class HttpRequest {

public:

 HttpRequest(const string& hostname) :

sock_(new Socket(hostname)) {}

 void send(string soapMsg) {sock << soapMsg;}

 ~HttpRequest {delete sock_;}

private:

 Socket* sock_;

};

void sendMyData(string soapMsg, string host) {

 HttpRequest req(host);

 req.send(soapMsg);

 //
Здесь делать ничего не требуется, так как когда req выходит

 // за диапазон, все очищается.

}

int main {

 string s = "xml";

 sendMyData(s, "www.oreilly.com");

}

Обсуждение

Гарантии, даваемые конструкторами и деструкторами, представляют собой удобный способ заставить компьютер выполнить всю очистку за вас. Обычно инициализация объекта и выделение используемых ресурсов производится в конструкторе, а очистка — в деструкторе. Это нормально. Но программисты имеют склонность использовать последовательность событий «создание-открытие-использование-закрытие», когда пользователю класса требуется выполнять явные открытия и закрытия ресурсов. Класс файла является хорошим примером.

Примерно так звучит обычный аргумент в пользу RAII. Я легко мог бы создать в примере 8.3 свой класс

HttpRequest
, который заставил бы пользователя выполнить несколько больше работы. Например:

class HttpRequest {

public:

 HttpRequest;

 void open(const std::string& hostname);

 void send(std::string soapMsg);

 void close;

 ~HttpRequest;

private:

 Socket* sock_;

};

При таком подходе соответствующая версия

sendMyData
может выглядеть так.

void sendMyData(std::string soapMsg, std::string host) {

 HttpRequest req;

 try {

req.open;

req.send(soapMsg);

req.close;

 } catch (std::exception& e) {

req.close; // Do something useful...

Поделиться:
Популярные книги

На границе империй. Том 9. Часть 3

INDIGO
16. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 3

Наследник

Майерс Александр
3. Династия
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Наследник

Мастер Разума II

Кронос Александр
2. Мастер Разума
Фантастика:
героическая фантастика
попаданцы
аниме
5.75
рейтинг книги
Мастер Разума II

Идеальный мир для Лекаря 21

Сапфир Олег
21. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 21

Прометей: Неандерталец

Рави Ивар
4. Прометей
Фантастика:
героическая фантастика
альтернативная история
7.88
рейтинг книги
Прометей: Неандерталец

Расплата. Отбор для предателя

Лаврова Алиса
2. Отбор для предателя
Фантастика:
фэнтези
5.00
рейтинг книги
Расплата. Отбор для предателя

Месть бывшему. Замуж за босса

Россиус Анна
3. Власть. Страсть. Любовь
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Месть бывшему. Замуж за босса

Кодекс Охотника. Книга VI

Винокуров Юрий
6. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга VI

Звездная Кровь. Изгой II

Елисеев Алексей Станиславович
2. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
технофэнтези
рпг
5.00
рейтинг книги
Звездная Кровь. Изгой II

Новый Рал 2

Северный Лис
2. Рал!
Фантастика:
фэнтези
7.62
рейтинг книги
Новый Рал 2

Адвокат Империи 7

Карелин Сергей Витальевич
7. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 7

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия

На прицеле

Кронос Александр
6. Лэрн
Фантастика:
фэнтези
боевая фантастика
стимпанк
5.00
рейтинг книги
На прицеле

Последняя Арена 11

Греков Сергей
11. Последняя Арена
Фантастика:
фэнтези
боевая фантастика
рпг
5.00
рейтинг книги
Последняя Арена 11