2015-09-23 3 views
3

Учитывая код (действительно псевдокод):ли деструктор пустого unique_ptr ж/о пользовательском Deleter тривиального

struct A { /* ... */ }; // assume is non-trivial 
struct B { /* ... */ }; // assume is non-trivial 

using UA = std::unique_ptr<A>; 
using UB = std::unique_ptr<B>; 

union U 
{ 

    UA a; 
    UB b; 

}; 

U u{std::make_unique<A>(/* init */)}; 
u.a = nullptr; // destructor of underlying type A called 
// u.a.~UA(); // destructor of smart pointer itself 
::new (&U.b) UB{std::make_unique<B>(/* init */)}; 

ли permittable опустить призвание деструктора для U::a члена? Вопрос навеян следующие quote относительно std::unique_ptr::~unique_ptr:

Если получить() == nullptr нет никаких эффектов.

Могу ли я считать, что d-tor в этом случае тривиален (описанный ниже смысл)?

Я думаю, что внутренний (и единственный в случае std::unique_ptr ж/о пользовательских Deleter) элемента данных (скажем p) из std::unique_ptr<T> имеет тип T *. После присвоения p = nullptr; кажется, что это невозможно сделать с таким std::unique_ptr, чтобы использовать его хранилище для других целей. Правильно ли это заключение?

+0

@deviantfan Это просто оптимизация. В реальной части кода (класс с кучей вариантов) я должен поменять две 'U'-подобные структуры. В этом коде нет места ':: new', и поэтому не должно быть явных вызовов деструкторов (просто идиома). – Orient

ответ

2

Могу ли я считать, что d-tor в этом случае тривиален?

Нет. Тривиальный деструктор - это формальный определенный член в C++, и непустой деструктор никогда не является тривиальным. Тривиальность - это свойство времени компиляции типа, поэтому деструктор, который должен выполнить проверку во время выполнения и условно назвать дебетер, не может быть тривиальным.

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

[basic.life] p4:

Для объекта типа класса с нетривиальным деструктором, программа не требуется вызывать деструктор явно перед хранением, который объект занимает повторно используется или выпущен; однако, если нет явного вызова деструктора или если для освобождения хранилища не используется выражение удаления (5.3.5), деструктор не должен быть неявно вызван, и любая программа, зависящая от побочных эффектов, создаваемых деструктор имеет неопределенное поведение.

Поскольку unique_ptr не имеет побочных эффектов, когда он пуст, программа не зависит от него, так что это нормально, чтобы пропустить запуск деструктор.

+0

's/doesnot not/does not /' Двойное отрицание - это начальная инструкция. – Orient