Должен ли я реализовать все свои классы данных как QSharedData и использовать его с QSharedDataPointer?

Я новичок в Qt и мне нужно написать несколько классов данных. Было бы хорошим подходом написать все эти классы, как в QSharedDataPointer пример ( здесь), или это слишком много накладных расходов (помимо того, что это больше работы)?

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

Мотивация для меня использовать QSharedData / QShareDataPointer - это упрощение ручного управления памятью и наличие общего стиля кода. Но я все еще не уверен, надзираю ли я за некоторыми оговорками.

Из примера:

class EmployeeData : public QSharedData
 {
 public:
     EmployeeData();
     EmployeeData(const EmployeeData &other);
     ~EmployeeData();

     int id;
     QString *name;
 };

 class Employee
 {
 public:
     Employee();
     Employee(int id, const QString &name);

     void setId(int id) { d->id = id; }
     void setName(const QString &name);

     int id() const { return d->id; }
     QString name() const;

 private:
     QSharedDataPointer<EmployeeData> d;
 };

1 ответ

Решение

Преимущества использования идиомы QSharedDataPointer/pImpl:

1) Вы можете избежать копирования некоторых данных в некоторых случаях (например, если у вас есть два или более идентичных объекта Employee, они могут совместно использовать один и тот же бэкэнд EmployeeData вместо того, чтобы у каждого была своя отдельная копия этих же данных)

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

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

Однако для вашей личной программы маловероятно, что вы увидите много пользы. Если ваши объекты данных такие же маленькие / простые, как те, что показаны в примере класса EmployeeData (или даже если они в 10 или 100 раз больше этого), издержки на простое создание копий данных, вероятно, будут минимальными... и так как вы можете, вероятно, перекомпилировать свою собственную кодовую базу всякий раз, когда вам нужно, преимущество обратной совместимости не имеет для вас никакого значения.

Поэтому я бы посоветовал сохранить простоту и просто делать вещи стандартным способом C++, делая обычные старые копии по умолчанию в стиле конструктора-копии ваших объектов-членов, когда это необходимо (и передавая ваши объекты в методы через const-reference, когда это возможно, для минимизации сколько раз они копируются). Если вы когда-нибудь заметили проблему измеримой производительности, в этот момент вы можете вернуться и переписать некоторые из ваших классов, используя pImpl/QSharedDataPointer, чтобы увидеть, дает ли это измеримое ускорение (хотя вы, вероятно, обнаружите, что это не так).

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