Using QList [] operator in const methods
-
As we know, you cannot use
QList []
operator in a method which isconst
, even when reading not trying to write a value. You must useat()
.OTOH C++ has no problems with native array
[]
operator.void Class::method() const { z = qlistMember.at(0); // OK z = qlistMember[0]; // Nope z = nativeArray[0]; // Yep nativeArray[0] = z; // Nope }
Personally I hate having to write
at(i)
instead of[i]
to read aQList
value in aconst
function. I would prefer having the C++ native array context semantics.Why is this either not available or not possible for a
QList
? Could it have been done when they wrote operator overloads by treatingconst
differently, and for whatever reason Qt has not implemented it, or is there a fundamental difference in C++ handling ofconst
/reads for native array[]
versus what you can write for your own operator overloads.Meanwhile I had a quick look at what
std::vector
does for this. It too has[]
operator and anat()
method. But if I understand right they differ for bounds checking not for read vs write? You can use their[]
operator in aconst
/read context.UPDATE
Investigating from @Kent-Dorfman's reply below, I think I am seeing thatQList []
operator is allowed (for reading) on aconst QList
after all, making my question irrelevant? But is this a change in Qt 6.x over 5.x?? -
Well, apologies, it seems this is non-question! I have gone back as far as the docs for Qt 5.10, which I think was around when I started Qt, and I still see there is a const T &QList::operator[](int i) const
Same as
at()
.So it has apparently always been possible to write
z = qlistMember[0];
in aconst
method! Yet at some point I thought I found this was not possible and made myself writeat()
for allQList
reads inconst
methods always. Maybe it was for some other type thanQList
with a[]
operator which did not offer aconst
overload and I got it fixed in my head...? -
Can you explain further? the const thing confuses me.
The bigger picture though is that lists are generally linked lists while vectors and arrays create adjacent cells across contiguous memory ranged. So non-overloaded [] will work on arrays (and vectors with the right type cast), but must be overloaded to work on a list.
Looks like in 6.9 there are actually two versions of QList::[]
QList<T>::reference operator[](qsizetype i) QList<T>::const_reference operator[](qsizetype i) const
-
Can you explain further? the const thing confuses me.
The bigger picture though is that lists are generally linked lists while vectors and arrays create adjacent cells across contiguous memory ranged. So non-overloaded [] will work on arrays (and vectors with the right type cast), but must be overloaded to work on a list.
Looks like in 6.9 there are actually two versions of QList::[]
QList<T>::reference operator[](qsizetype i) QList<T>::const_reference operator[](qsizetype i) const
@Kent-Dorfman said in Using QList [] operator in const methods:
Can you explain further? the const thing confuses me.
Don't know what more to say than [Note: I have corrected my earlier method code to make it clear the method is
const
, which I failed to do, sorry if that confused.]void Class::method() const { z = qlistMember[0]; // Nope z = nativeArray[0]; // Yep }
You cannot use
QList []
operator even to read a value from aQList
where the list isconst
/read-only, either by declaring itconst QList<>[]
explicitly or by it being a class member variable not itselfconst
but inside aconst
member method, so it is implicitlyconst
in that method.Linked lists vs contiguous memory is not in itself germane.
Looks like in 6.9 there are actually two versions of QList::[]
Well that would make a huge difference, that's exactly what I would have liked. And I believe I can use
z = qlistMember[0]; // Nope
in my Qt 6.4 or 6.5 after all. But I am "pretty sure" this was not possible in Qt 5.x, was it? Did this change?? -
Well, apologies, it seems this is non-question! I have gone back as far as the docs for Qt 5.10, which I think was around when I started Qt, and I still see there is a const T &QList::operator[](int i) const
Same as
at()
.So it has apparently always been possible to write
z = qlistMember[0];
in aconst
method! Yet at some point I thought I found this was not possible and made myself writeat()
for allQList
reads inconst
methods always. Maybe it was for some other type thanQList
with a[]
operator which did not offer aconst
overload and I got it fixed in my head...? -
J JonB has marked this topic as solved
-
Well, apologies, it seems this is non-question! I have gone back as far as the docs for Qt 5.10, which I think was around when I started Qt, and I still see there is a const T &QList::operator[](int i) const
Same as
at()
.So it has apparently always been possible to write
z = qlistMember[0];
in aconst
method! Yet at some point I thought I found this was not possible and made myself writeat()
for allQList
reads inconst
methods always. Maybe it was for some other type thanQList
with a[]
operator which did not offer aconst
overload and I got it fixed in my head...?@JonB said in Using QList [] operator in const methods:
Maybe it was for some other type than QList with a [] operator which did not offer a const overload and I got it fixed in my head...?
Yes. QMap and QHash.
-
@JonB said in Using QList [] operator in const methods:
Maybe it was for some other type than QList with a [] operator which did not offer a const overload and I got it fixed in my head...?
Yes. QMap and QHash.
@Christian-Ehrlicher
Yes, it could have been that I extrapolated from those toQList
/QVector
s when that was not the case. I am still surprised that I was so sure it was the case. Anyway I am much happier now that I know that I can use[]
for read onconst
lists/vectors instead of having to typeat()
, going forward from now. -
QMap and QHash do offer a const operator[]. std::map is the one without the const overload.
QMap does this by changing the return type from T& to T. A conscious choice was made not to do that in the standard library. -
My spidey sense was telling this has something to do with returning a reference instead of a copy. I could picture grabbing a reference to an entry in the container and then that element being deleted, and Boom! stuff breaks.
-
My spidey sense was telling this has something to do with returning a reference instead of a copy. I could picture grabbing a reference to an entry in the container and then that element being deleted, and Boom! stuff breaks.
@Kent-Dorfman said in Using QList [] operator in const methods:
My spidey sense was telling this has something to do with returning a reference instead of a copy. I could picture grabbing a reference to an entry in the container and then that element being deleted, and Boom! stuff breaks.
You'll only get a const reference returned if the QList is const (inside the currently visible scope). Nobody is going to change it while it is const (I know, it is a simplified assumption without any multithreading involved). You also have to be explicit in having a const reference instead of a copy;
auto
or justT
(T being the type inside the QList) will give you a copy. You have to addconst
and&
yourself. And hopefully you know what you are doing if you do this. Usually, this is not a problem if your const reference is not a member variable (and reference member variables can only be assigned once inside the constructor which is why you'll rarely see them in the wild).Even if
operator[](int) const
returns a copy you have the exact same possible race condition in a multithreading environment. The only advantage is that it is fewer lines of code where this might occur. -
@Kent-Dorfman said in Using QList [] operator in const methods:
My spidey sense was telling this has something to do with returning a reference instead of a copy. I could picture grabbing a reference to an entry in the container and then that element being deleted, and Boom! stuff breaks.
You'll only get a const reference returned if the QList is const (inside the currently visible scope). Nobody is going to change it while it is const (I know, it is a simplified assumption without any multithreading involved). You also have to be explicit in having a const reference instead of a copy;
auto
or justT
(T being the type inside the QList) will give you a copy. You have to addconst
and&
yourself. And hopefully you know what you are doing if you do this. Usually, this is not a problem if your const reference is not a member variable (and reference member variables can only be assigned once inside the constructor which is why you'll rarely see them in the wild).Even if
operator[](int) const
returns a copy you have the exact same possible race condition in a multithreading environment. The only advantage is that it is fewer lines of code where this might occur.@SimonSchroeder said in Using QList [] operator in const methods:
Even if
operator[](int) const
returns a copy you have the exact same possible race condition in a multithreading environment. The only advantage is that it is fewer lines of code where this might occur.Multithreading seems an irrelevant point though because the competent programmer understands that accessing a shared resource needs a mutex, so if safe programming processes are observed then there is no race condition.
re const vs non-const: totally agree and get it. It's the way things are...however, I do sometimes wish nothing was ever const and everything was mutable. :^)