Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ | страница 66



Правило простое: если вы используете [] в выражении new, то должны использовать [] и в соответствующем выражении delete. Если вы не используете [] в new, то не надо использовать его в соответствующем выражении delete.

Это правило особенно важно помнить при написании классов, содержащих указатели на динамически распределенную память, в которых есть несколько конструкторов, поскольку в этом случае вы должны использовать одинаковую форму new во всех конструкторах для инициализации членов-указателей. Если этого не сделать, то как узнать, какую форму delete применить в деструкторе?

Данное правило для тех, кто часто прибегает к использованию typedef, поскольку из него следует, что автор typedef должен документировать, какую форму delete применять для удаления объектов типа, описываемого typedef. Рассмотрим пример:


>typedef std::string AddressLines[5]; // адрес человека состоит из 4 строк,

>// каждая из которых имеет тип string


Поскольку AddressLines – массив, то следующему применению new


>std::string *pal = new AddressLines; // отметим, что “new AddressLines”

>// вернет string *, как и

>// выражение “new string[4]”


должна соответствовать форма delete для массивов:


>delete pal; // не определено!

>delete[] pal; // правильно


Чтобы избежать путаницы, старайтесь не примененять typedef для определения типов массивов. Это просто, потому что стандартная библиотека C++ (см. правило 54) включает шаблонные классы string и vector, позволяющие практически полностью избавиться от динамических массивов. Так, в примере выше AddressLines можно было бы определить как вектор строк: vector.

Что следует помнить

• Если вы используете [] в выражении new, то должны применять [] и в соответствующем выражении delete. Если вы не используете квадратные скобки [] в выражении new, то не должны использовать их и в соответствующем выражении delete.

Правило 17: Помещение в «интеллектуальный» указатель объекта, вьщеленного с помощью new, лучше располагать в отдельном предложении

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


>int priority();

>void processWidgets(std::tr1::shared_ptr pw, int priority);


Помня о премудростях применения объектов, управляющих ресурсами (см. правило 13), processWidgets использует «интеллектуальный» указатель (здесь – tr1::shared_ptr) для обработки динамически выделенного объекта. Рассмотрим теперь такой вызов processWidgets: