Обобщая общие указатели и QSharedPointer::data() против shared_ptr::get()?

Я сделал библиотеку Qt, которая построена на давних абстракциях, таких как QSharedDataPointer а также QSharedData, Поэтому, когда мне нужен был обычный разделяемый указатель, имело смысл QSharedPointer для согласованности.

Я сейчас использую это в проекте C++11. Чтобы сделать код более стандартным, я переключаюсь на shared_ptr для всех своих локальных подсистем.

Зависимость C++11 внутри самой библиотеки не обязательно желательна, поэтому казалось, что вы должны быть в состоянии выбрать, какой тип общего указателя вы хотите использовать. В качестве первого шага, чтобы двигаться вперед, я попробовал этот метод, предложенный в Гибкость псевдонима шаблона в C++ 0x (по общему признанию, сама зависимость C++11, но я мог бы использовать препроцессор через флаг компилятора в не-C++11 строит)

#if THINKERQT_USE_STD_SHARED_PTR

#include <memory>
template<class T>
using shared_ptr_type = std::shared_ptr<T>;

#else

#include <QSharedPointer>
template<class T>
using shared_ptr_type = QSharedPtr<T>;

#endif

К сожалению, классы указателей выбрали разные имена для методов. Примечательно, что доступ к содержащемуся указателю осуществляется .get() в shared_ptr и .data() в QSharedPointer.

Я собирался сделать экстрактор, какой-то shared_ptr_type_get<> но затем заметил, что можно эффективно добиться того же (в тех случаях, когда содержащийся указатель не является нулевым, и я могу проверить на нулевое значение с помощью логического приведения) с помощью:

&(*ptr)

Если вы читаете код, это немного замедляет работу, и некоторые вещи, которые кто-то может попытаться оптимизировать (затем быстро понять, что это не сработает). Но кроме фактора WTF, это кажется достаточно безобидным... не так ли?

1 ответ

Решение

Я использую это и в своем проекте, и в этом нет ничего плохого, кроме читабельности, как вы уже заметили. И, как отметил Майк Сеймур, вы всегда должны проверять, что ptr не является нулевым указателем.

Я использую следующие идиомы в большинстве случаев:

if( shared_ptr_type ptr = funcReturnsSharedPtr() )
{
    funcAcceptsRawPtr(&*ptr);
}

В значительной степени гарантируется, что он будет компилироваться и функционировать правильно независимо от того, какой тип общего указателя вы используете shared_ptr_type поскольку любой разумный класс общего указателя будет перегружен operator*,

Другие вопросы по тегам