3

I have a class Foo that has defined a public struct Data inside of it, with a QVector<Data> allData nesting multiple objects of the Data struct inside of it:

class Foo
{
    public:
        struct Data {
            uchar valueA;
            uchar valueB;
            uchar valueC;
        };
    private:
        QVector<Data> allData;
};

I also have two other classes B and C that need to read allData multiple times a second. They shall not be able to write into allData at all, this shall be handled by the Foo class only.

With performance in mind, I'm looking for a way to do this without creating a new QVector everytime. As far as I understand, a method like this:

QVector<Data> getAllData() {
    return allData;
}

would result in a new object being created everytime this method gets called.

If I gave the other classes something like a QVector<Data> allDataCopy that is just being handed over to Foo to be filled with the values inside of allData that would just result in having to copy all values everytime, which I imagine would not be very perfomant aswell.

Is there any efficient way to solve this?

ExtraGoofy
  • 41
  • 6

2 Answers2

4

Your "getters" should not return by value unless you want to force a copy on the user. Provide two overloads that will respectively return an lvalue reference and a const lvalue reference (or only the const one if you don't want users of Foo to mutate allData):

QVector<Data>& getAllData() {
    return allData;
}

const QVector<Data>& getAllData() const {
    return allData;
}

This will still allow your user to make a copy (if wanted), but also enable your user to just observe/mutate allData through a reference, without any copy.


In C++11 and above, if QVector supports move semantics, you might want to overload on the && ref qualifier as well:

QVector<Data>& getAllData()       &      { return allData; }
const QVector<Data>& getAllData() const& { return allData; }
QVector<Data> getAllData()        &&     { return std::move(allData); }

This allows users to conveniently move allData from an rvalue of type Foo.

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
3

QVector is cheap to copy; it uses smart reference copy on write semantics.

If your code has any danger of multiple thread access, QVector const& is dangerous, as references are not thread safe. The same kind of danger can occur if you are reentrant, and cause the QVector to be modified while someone else is holding onto the QVector const&.

Simply return a copy of QVector. Fancy alternatives involving references can cause potential bugs, do not consider them until you have evidence that the small cost of "copying" a QVector is causing performance issues.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524