問題描述
根據這個演講在 Qt 容器上使用 C++11 范圍基礎 for
時的陷阱.考慮:
According to this talk there is a certain pitfall when using C++11 range base for
on Qt containers. Consider:
QList<MyStruct> list;
for(const MyStruct &item : list)
{
//...
}
根據談話,陷阱來自隱式共享.在引擎蓋下,基于范圍的 for 從容器中獲取迭代器.但是因為容器不是 const,所以 interator 將是非常量的,這顯然足以讓容器分離.
The pitfall, according to the talk, comes from the implicit sharing. Under the hood the ranged-based for gets the iterator from the container. But because the container is not const the interator will be non-const and that is apparently enough for the container to detach.
當您控制容器的生命周期時,這很容易解決,只需將 const 引用傳遞給容器以強制它使用 const_iterator 而不是分離.
When you control the lifetime of a container this is easy to fix, one just passes the const reference to the container to force it to use const_iterator and not to detach.
QList<MyStruct> list;
const Qlist<MyStruct> &constList = list;
for(const MyStruct &item : constList)
{
//...
}
但是,例如容器作為返回值.
However what about for example containers as return values.
QList<MyStruct> foo() { //... }
void main()
{
for(const MyStruct &item : foo())
{
}
}
這里發生了什么?容器還在復制嗎?直覺上我會說這是為了避免可能需要這樣做?
What does happen here? Is the container still copied? Intuitively I would say it is so to avoid that this might need to be done?
QList<MyStruct> foo() { //... }
main()
{
for(const MyStruct &item : const_cast<const QList<MyStruct>>(foo()))
{
}
}
我不確定.我知道它有點冗長,但我需要這個,因為我在大型容器上大量使用基于范圍的 for 循環,所以談話對我來說是正確的.
I am not sure. I know it is a bit more verbose but I need this because I use ranged based for loops heavily on huge containers a lot so the talk kind of struck the right string with me.
到目前為止,我使用輔助函數將容器轉換為常量引用,但如果有更簡單/更短的方法來實現相同的目標,我希望聽到它.
So far I use a helper function to convert the container to the const reference but if there is a easier/shorter way to achieve the same I would like to hear it.
推薦答案
template<class T>
std::remove_reference_t<T> const& as_const(T&&t){return t;}
可能會有所幫助.由于非常量迭代,返回右值的隱式共享對象可以隱式檢測寫入分片(和分離).
might help. An implicitly shared object returned an rvalue can implicitly detect write-shraring (and detatch) due to non-const iteration.
這給你:
for(auto&&item : as_const(foo()))
{
}
它允許您以 const 方式(而且非常清楚)進行迭代.
which lets you iterate in a const way (and pretty clearly).
如果你需要引用生命周期延長來工作,有 2 個重載:
If you need reference lifetime extension to work, have 2 overloads:
template<class T>
T const as_const(T&&t){return std::forward<T>(t);}
template<class T>
T const& as_const(T&t){return t;}
但是迭代 const 右值并關心它通常是一個設計錯誤:它們是丟棄的副本,為什么編輯它們很重要?如果你基于 const 限定的行為非常不同,那會在其他地方咬你.
But iterating over const rvalues and caring about it is often a design error: they are throw away copies, why does it matter if you edit them? And if you behave very differently based off const qualification, that will bite you elsewhere.
這篇關于在 Qt 中正確使用 C++11 基于范圍的 for 循環的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!