уникальный ptr — C ++ / pimpl: необработанный указатель или unique_ptr? Какой выбор лучше?

Когда вы используете unique_ptr<T> для форвард объявленного типа T, unique_ptr деструктор требует T завершено, но оператор присваивания перемещения также (и reset), согласно этой таблице:

https://stackoverflow.com/a/6089065/1794803

Итак, для вашего pImpl идиома, чтобы реализовать это правильно, вы должны объявить delete и move assignment method (который, как побочный эффект, помечает их как не встроенные):

class impl_t;

class A
{
std::unique_ptr<impl_t> p_impl;

public:
// Implement in A.cpp as A::~A() = default;
~A();

// Implemented in A.cpp as A& operator=(A&&) = default;
A& operator=(A&& he);
};

Но с тех пор std::unique_ptr RAII-решение для динамической памяти, а вы pImpl уже находится внутри класса, и вы все равно вынуждены написать деструктор, не лучше ли просто управлять необработанным указателем, поскольку ваш класс уже RAII-подобен с точки зрения p_impl?:

class impl_t;

class A
{
impl_t* p_impl;

public:
~A(); // The destructor must be written anyway.

// The omitted move assignment destructor doesn't cause UB.
};

Разве это не лучшее решение? (+ определили или удалите свой собственный оператор копирования / перемещения, если вы хотите, чтобы класс был копируемым / подвижным или нет; но это «сознательный выбор»; однако, не пишите назначение перемещения для unique_ptr это ошибка).

Используя unique_ptr только спасает тебя за написанное delete p_impl в деструкторе, который вы должны объявить в любом случае.

unique_ptr является отличным выбором для локальных динамических объектов, которые будут уничтожены даже в случае исключений, но для «атрибутов» вы ничего не экономите, кроме возможности получить UB, если вы не помните, что вам нужно переписать оператор присваивания перемещения.

2

Решение

Ну, используя std::unique_ptr избавляет вас от беспокойства с явным delete для p_impl.

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

4

Другие решения

std :: unique_ptr должен быть предпочтительным способом для pimpl. Для справки см. Выступление Херба Саттера на CppCon16 около 10 минут.
Причина в том, что это предотвратит случайную смену прыща при проведении RAII.

0

По вопросам рекламы [email protected]