I am a Qt beginner and need to write some data classes. Would it be a good approach to write all these classes as in the QSharedDataPointer
example (here), or is this too much overhead (besides the fact it is more work)?
My classes in nature a very much like the below Employee
class. I'll have to deal with several hundreds of instances, not ten-thousands or millions.
A motivation for me to use QSharedData / QShareDataPointer would be the simplification of manual memory management and having a common code style. But I am still not sure whether I oversee some caveats.
From the example:
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;
};
The advantages of doing the QSharedDataPointer/pImpl idiom would be:
1) You can avoid some data copying in some cases (e.g. if you have two or more identical Employee objects, they can share the same EmployeeData back-end, rather than each having their own separate copy of that same data)
2) After you add extra data fields to the EmployeeData class, only the source code for the Employee class would need to be recompiled, because only the Employee class (presumably) ever accesses the EmployeeData class directly. All your other code would (presumably) access the Employee class only, and therefore would not need to be recompiled because the Employee class's size and layout would not have changed.
Both of those reasons can be compelling in the right circumstances -- Qt itself, for example, benefits from pImpl and implicit sharing in many places because Qt needs to handle large quantities of data extremely efficiently, and more importantly because Qt's relationship with third-party developers requires it to guarantee that new Qt shared-library versions will remain backwards-compatible with existing third-party application executable code that was compiled against older Qt versions.
For your personal program, however, it's unlikely that you'll see much benefit. If your data objects are as small/simple as the one shown in the EmployeeData example class (or even if they are 10 or 100 times bigger than that), the overhead of just making copies of the data will likely be minimal... and since you can presumably recompile your own codebase whenever you need to, the backwards-compatibility benefit doesn't really matter for you.
So my advice would be to keep it simple and just do things the standard C++ way, making regular old default-copy-constructor style copies of your member objects when necessary (and passing your objects to methods via const-reference when possible, to minimize the number of times they get copied). If you ever notice a measurable performance problem, at that point you could go back and rewrite some of your classes using pImpl/QSharedDataPointer to see if it gives you a measurable speedup (although you'll likely find that it won't).