«Атомные» функции размещения и построения C ++ являются правильными и безопасными для исключений: If new T
;броски, ничего не протекает, и если new T[N]
бросает куда-нибудь по пути, все, что уже было построено, уничтожается.Так что не о чем беспокоиться.
Теперь отступление:
То, о чем вы всегда должны беспокоиться, это использование более чем одного new
выражения влюбая единица ответственности.По сути, вы должны рассматривать любое выражение new
как «горячую картошку», которая должна быть поглощена полностью созданным, ответственным объектом-хранителем.
Рассматривать new
и new[]
строго как строительные блоки библиотеки:Вы никогда не будете использовать их в высокоуровневом пользовательском коде (возможно, за исключением одного new
в конструкторе) и только внутри библиотечных классов.
Для:
// BAD:
A * p = new A;
B * q = new B; // Ouch -- *p may leak if this throws!
// Good:
std::unique_ptr<A> p(new A);
std::unique_ptr<B> q(new B); // who cares if this throws
std::unique_ptr<C[3]> r(new C[3]); // ditto
В качестве еще одного отступления: стандартные библиотечные контейнеры реализуют аналогичное поведение: если вы говорите resize(N)
(растущий), и во время любых конструкций возникает исключение, тогда всех изуже построенные элементы разрушаются.То есть resize(N)
либо увеличивает контейнер до указанного размера, либо не увеличивает его вообще. (Например, в GCC 4.6 см. Реализацию _M_fill_insert()
в bits/vector.tcc
для библиотечной версии построения диапазона с проверкой на исключение.)