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)
{
//...
}
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 iterator will be non-const
and that is apparently enough for the container to detach.
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()))
{
}
}
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 shorter/easier way to achieve the same I would like to hear it.
const MyStruct& const item : foo()
to iterate in const style. – Neumeyerfor(const auto& bla : blas)
i dont see there could be a problem with this even – Corrconst QList<MyStruct> &constList = list;
instead ofQlist<MyStruct> &constList = list;
to get const iterators and prevent detach? If no, why not? – BuglossQList<MyStruct> &constList = foo();
and thenfor(const MyStruct &item : constList)
solve your initial problem? – BuglossQList<MyStruct> &constList = foo();
when it won't detach in this case:const QList<MyStruct> &constList = list;
? – Buglossconst QList<MyStruct> constList = foo();
So now we have const Container and no detach so far. Is that right? And now we pass the const Container to the for loopfor(const MyStruct &item : constList)
. Since the Container is const it will use const iterators and also no detach. Or getting here something wrong? – Bugloss