目前我正在做一些代碼審查并偶然發現以下結構:
QVariantMap argumentMap = QJsonDocument::fromJson(" ... JSON-String ... ", &error).toVariant().toMap();
...
QListIterator<QVariant> keyIterator( argumentMap["key"].toList() );
while ( keyIterator.hasNext() ) ...
我的第一個感覺是這里的迭代器有問題,因為toList()回傳一個QVariantListby 值導致一個臨時物件。
因此,Ctor 被定義為QListIterator(const QList<T> &list),我們發現了這一點 [1]:“將臨時物件的生命周期延長到參考它的 const 參考的生命周期是 C 的官方特性。” 但首先我的論點是對串列的 const 參考的生命周期系結到 Ctor。
所以我試圖深入研究 QListIterator [2] 的定義:
Q_DECLARE_SEQUENTIAL_ITERATOR(List)
#define Q_DECLARE_SEQUENTIAL_ITERATOR(C) \
\
template <class T> \
class Q##C##Iterator \
{ \
typedef typename Q##C<T>::const_iterator const_iterator; \
Q##C<T> c; \
const_iterator i; \
public: \
inline Q##C##Iterator(const Q##C<T> &container) \
: c(container), i(c.constBegin()) {} \
現在,我真的很困惑!:) 似乎與c成員一起,迭代器擁有它自己的串列本地副本。所以最后,我會說這種用法是絕對有效的。有人可以確認一下嗎?
另外,這個結構在整個應用程式中使用,顯然從未引起任何問題。
簡短的附錄:
我在這里 [3] 也發現了這個:“如果你想使用 STL 迭代器迭代這些,你應該總是獲取容器的副本并迭代副本。例如:”
// WRONG
QList<int>::const_iterator i;
for (i = splitter->sizes().begin(); i != splitter->sizes().end(); i)
首先,我認為這是完全相同的問題,但再想一想,我現在會說這里的問題是,begin()并且在串列的不同副本上end()被呼叫。正確的?
[1] https://blog.galowicz.de/2016/03/23/const_reference_to_temporary_object/
[2] https://code.woboq.org/qt5/qtbase/src/corelib/tools/qiterator.h.html
[3] https://doc.qt.io/qt-5/containers.html#stl-style-iterators
uj5u.com熱心網友回復:
本QListIterator應該是很好的,因為它需要在串列的副本。
您所指的臨時檔案的生命周期延長是這樣的:
{
auto const & myRef = foo.bar(); // returns by value so it returns a temporary
// you would expect the temporary to be gone now
// and myRef thus being a dangling reference, but it is not!
myRef.doSomething(); // perfectly fine
}
// now that myRef is out of scope also the temporary is destroyed
有關生命周期的描述,請參見此處。
然而,在這種情況下這無關緊要,因為這種機制不能將臨時物件的生命周期延長到物件的生命周期,而只能延長到參考的生命周期。
是的,由于您給出的原因,最后一個示例是錯誤的:將迭代器與不同的(臨時)物件進行比較。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/378527.html
