новый тогда кинь в конструктор C ++? - PullRequest
5 голосов
/ 28 декабря 2011

Если я сделаю

Bat::Bat() : m_member_str(new std::string("Am I freed?"))
{
  throw std::runtime_error("oops");
}

Будет ли new выделено std::string освобождено?Я думал, что это может быть потому, что деструктор не вызывается.

Я не использую std :: string , но мой собственный класс, просто показывая его в качестве простого примера.

Ответы [ 4 ]

3 голосов
/ 28 декабря 2011

Полностью построенные объекты называют деструкторами.Частично построенные объекты этого не делают.

В вашем случае ваш Bat объект частично создан, потому что вы выбросили исключение из его конструктора.Поэтому ~Bat() будет не вызываться.

m_member_str однако полностью построен, и поэтому будет вызываться его деструктор .Однако мы не можем увидеть тип этого объекта.

Если это std::string*, то ничего не произойдет.Это указатель, и уничтожение указателя не удаляет память, на которую он указывает.

Если это некая форма интеллектуального указателя, то будет вызван его деструктор, и он будет безопасно обрабатывать выделенную вами память.

В общем, если ваши члены являются объектами RAII и имеют значимый деструктор, они будут очищаться независимо от того, что.

Если нет, как в этом случае, то выпридется разобраться с последствиями самостоятельно, возможно, bny поймает исключение, освободит память и затем сбросит.

3 голосов
/ 28 декабря 2011

Этот пример - классический пример использования умных указателей.Bat не полностью построен, поэтому не будет вызван деструктор, но будет деструктор для m_member_str и всех других полностью созданных членов.Если вам не нужен уродливый блок, такой как try { foo(); } catch (...) { delete m_member_str; }, вам придется освоиться с RAII.

std::auto_ptr или boost::scoped_ptr помогут вам в C ++ 03 или их эквивалентах вC ++ 11.Существует очень мало недостатков в использовании их для собственных указателей членов.

1 голос
/ 28 декабря 2011

Вы полностью изменили свой вопрос - аннулировали мой первоначальный ответ! ; -Р

Распределена ли строка с новым освобожденным?

нет

Нет

Я думал, что это может быть только потому, что деструктор не называется

Не актуально. Чтобы получить освобождение, вам в основном нужно иметь созданный объект, для которого будет вызываться деструктор , и в котором конструктор выполняет освобождение (или вы можете использовать блок try / catch и делать все это явно).

так как я могу освободить m_member_str, если это был указатель на член?

(Во-первых, лучший общий подход - сделать переменную-член m_member_str строкой, а не указателем на строку - тогда строковый деструктор очистится.)

Если у вас должен быть указатель, используйте умный указатель для захвата указателя так, чтобы деструктор умного указателя разрушал указанный объект , а освобождает память. Это будет вызвано тем, что сбойный конструктор уничтожит уже созданные переменные-члены во время обработки исключений.

1 голос
/ 28 декабря 2011

Нет, этот объект будет протекать, если вы не позаботитесь об этом.Лучший способ - использовать умный указатель для переменной-члена.Общее правило заключается в том, что полностью построенные объекты уничтожаются при разматывании стека, и то же самое относится к переменной m_member_str, но, поскольку это необработанный указатель, деструктор будет тривиальным и не будет касаться наведенного объекта.

...