> 13 мая 2020 г., в 09:04, Lars Knoll <lars.kn...@qt.io> написал(а):
>
> The above example is rather weirdly constructed.
>
> But anyhow, those data lifetime issues when using views as return values
> extensively are a lot less obvious to spot when a human reads the code. APIs
> should be safe to use wherever possible, so that our users don’t have to
> worry about those things. This will lead to fewer bugs in the resulting code
> and faster development times. Trading that for some saved CPU cycles is in
> almost all cases (and yes there are exceptions in low level classes) a very
> bad deal.
Well, I can’t say that returning COW container is an easy thing to do. It’s a
trade-off between «safety» and «some CPU cycles». And I’d say it’s much better
if app crashes compared to the case where I have spent ages in profiler fixing
performance bugs introduced by the developers who doesn’t really know how COW
works (e.g. use operator[] instead of .at(), hidden detaches)
There's already a «-Wclazy-range-loop» warning in Clazy about detaching COWs:
From Qbs code (which is written by the developers who are supposed to know COW
problems):
1. for (const QString &abi: rhs.split(QLatin1Char(' '))) // attempt to detach
2. QList<ProductData> ProjectData::products() const { return d->products; }
for (const ProductData &p : project.products()) // oops, deep copy
And I can’t say that creating a variable on the stack before every for-loop is
an easier way for users (note, qAsConst doesn’t work for temporaries and it
should not).
The point is - there’s already a check in Clazy that does the similar check -
on can add a check for using a views from temporary.
And the lifetime issues only come into play when mixing views and non-views
approach:
Object myObject;
auto view1 = myObject.getView()[42].getView(); // safe!
auto view2 = myObject.getReference()[42].getView(); // safe!
auto view3 = myObject.getCopy()[42].getView(); // not safe, copy is destroyed
> You can just as well argue the other way round. Returning a view requires the
> class to store the data in continuous memory. It can’t create it on the fly
> if asked.
How often is such a use-case, when you realize that you need to change the
simple getter to a container?
Why cannot you simply add a method with a new name in that case?
Am not really advocating for returning views, but it’s not that black and white
as you described, that’s a trade-off.
What I am advocating for is that functions should take views where possible -
this is perfectly safe (you can pass temporaries into a view) and leads to much
easier code in some cases (users can pass unicode literals, std::wstring,
QVector<QChar> and so on).
Ivan
_______________________________________________
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development