Results 1 to 13 of 13

Thread: Why const can disappear at QMap::value(...)

  1. #1
    Join Date
    Nov 2015
    Posts
    17
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Why const can disappear at QMap::value(...)

    Hello,

    I have some basic questions, I'm very interested in.

    If I have a QMap<int,MyObject*>* and call method value on it, the method returns a pointer to a const instance of MyObject.
    Qt Code:
    1. QMap<int,MyObject*>* myMap = new QMap<int,MyObject*>();
    2. myMap->insert(1,new MyObject());
    3.  
    4. MyObject const * object_one = myMap->value(1); // const instance of myObject. I'm not allowed to call non-const methods on it.
    5. object_one->changeMe(); //compiler will complain about it
    To copy to clipboard, switch view to plain text mode 

    but I can write it like this:
    Qt Code:
    1. MyObject * object_one = myMap->value(1); // non-const instance of myObject. I'm allowed to call non-const methods on it.
    2. object_one->changeMe(); //compiler wont't complain about it
    To copy to clipboard, switch view to plain text mode 

    And now I can mutate the instance. I want to know if this works just because of c-compatibility, if it's ok to use it like that (I would say no)?

    Further I want to know how should I pass such an instance to another object which should hold the instance as mutable member (MyObject* myobject):

    Qt Code:
    1. OtherClass(MyObject * myobject) : myobject(myobject){ }
    2.  
    3. MyObject const * const_object_one = myMap->value(1); // const instance of myObject. I'm not allowed to call non-const methods on it.
    4. MyObject * object_one = myMap->value(1); // non-const instance of myObject. I'm allowed to call non-const methods on it.
    5.  
    6. OtherClass* other_object = new OtherClass(const_object_one);//fails
    7.  
    8. OtherClass* other_object = new OtherClass(object_one);//works
    To copy to clipboard, switch view to plain text mode 

    Can I call the constructor passing the object via QMap::value, or should I use []->operator?

    Thank you
    Last edited by QtCrawler; 17th December 2015 at 08:18.

  2. #2
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Why const can disappear at QMap::value(...)

    These are basic C++ questions, indeed.

    MyObject const * object_one; declares object_one as a pointer to a const MyObject. You promise not to modify the MyObject instance through object_one.

    Remember that an instance method has a hidden parameter: the "this" pointer to the receiver object. Just like any other pointer (or reference) parameter, you can specify whether it is const or not. To make it const, just qualify the method prototype itself with "const". A const method only has const access to *this. A non-const method has full access to *this, but can only be called for non-const objects. This is really the same as any other pointer or reference parameter.

    The changeMe() method presumably is a non-const method that mutates *this, and the compiler refuses to call it for the const object *object_one.

    So, if you want to mutate *object_one, just declare it as a non-const pointer.

    Similarly, OtherClass::OtherClass(MyObject * myobject), as its signature implies, wants full access to *myobject, therefore you may not pass a const pointer as argument. If const access to *myobject is enough, you should change the signature to OtherClass::OtherClass(const MyObject * myobject).

    QMap::value() and QMap::operator[] do two different things.

    QMap::value() returns a copy of a value in the map. It is a const method because it does not need to mutate the QMap.

    QMap::operator[] is overloaded. It has a const version (called for const QMaps) and a non-const version (called for non-const QMaps).
    The const version does the same thing as QMap::value().
    The non-const version finds the value for the given key. If it does not exist, it mutates the QMap by inserting a new value. In both cases, it returns a non-const reference to the value (as opposed to a copy), which you can then use to mutate the value.

  3. The following user says thank you to yeye_olive for this useful post:

    QtCrawler (17th December 2015)

  4. #3
    Join Date
    Nov 2015
    Posts
    17
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Why const can disappear at QMap::value(...)

    Ok tanks.

    So I can use MyObject * object_one = myMap->value(1); and it is completely valid, although value() returns MyObject const * object_one (which is a copy of the value in the map).
    Is this comparable to this?
    Qt Code:
    1. QMap<QString,QString> stringMap;
    2. stringMap.insert("key","value");
    3.  
    4. QString value1 = stringMap.value("key"); //same would be QString value1(stringMap.value("key"));
    To copy to clipboard, switch view to plain text mode 

    I don't unterstand following:

    assigning a pointer to a const instance to a pointer to a non-const instance works here:
    Qt Code:
    1. MyObject * object_one = myMap->value(1);
    To copy to clipboard, switch view to plain text mode 
    but it does not work in constructor, i.e. pass the const instance to a pointer to the constructor and assign it to the pointer to a non-const instance which is a member.
    Qt Code:
    1. OtherClass(const MyString * str){
    2. this->str = str;
    3. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by QtCrawler; 17th December 2015 at 13:26.

  5. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,325
    Thanks
    316
    Thanked 871 Times in 858 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Why const can disappear at QMap::value(...)

    but it does not work in constructor, i.e. pass the const instance to a pointer to the constructor and assign it to the pointer to a non-const instance which is a member.
    That's as it should be. Passing a const pointer and trying to assign it to a non-const pointer member variable breaks the promise that you will not modify the instance the pointer refers to. Even if you don't actually call any non-const methods using your copy of the pointer, the compiler has no way of knowing that in the constructor so it doesn't allow you to make a non-const copy of the pointer.

    If indeed you never do call any non-const methods using the copy of the pointer, then simply declare the member variable as a const pointer and assign it in the constructor.

    assigning a pointer to a const instance to a pointer to a non-const instance works here:
    Actually, it shouldn't work. There is no non-const counterpart to value() as there is for operator[]. If that code actually compiles, I don't know why.

    In the case of your QMap<QString, QString> example, line 4 is actually creating a new QString instance using the copy constructor from the const QString instance returned by value(). It is a duplicate of the one in the map, and you can change it to whatever you wish without changing the value that is held in the map. And in fact, in line 2 where you insert the string literal into the map, this is making a copy, too, and the string literal will disappear once the insert() statement exits.
    Last edited by d_stranz; 17th December 2015 at 23:55.

  6. The following user says thank you to d_stranz for this useful post:

    QtCrawler (18th December 2015)

  7. #5
    Join Date
    Nov 2015
    Posts
    17
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Why const can disappear at QMap::value(...)

    thnq d_stranz! The explanation is very clear.
    Actually, it shouldn't work. There is no non-const counterpart to value() as there is for operator[]. If that code actually compiles, I don't know why.
    I'm very interested in, why this works, and indeed it works. I tried it with gcc under unix and mingw under windows. Both worked.

    Is it right if I say: If I have a Qt-Container containing pointers to Objects and I want to iterate over them and call a non-const method of the instance during iteration, I should never use the the standard iterators (QMapIterator, QListIterator, QHashIterator)?
    Should I use instead the mutable counterparts (QMutableListIterator, QMutableMapIterator, etc...)? Or is it better to use patterns like this:
    Qt Code:
    1. foreach(MyObject* cObject,values){//values is a list of MyObject-instances QList<MyObject*> values;
    2. cObject->setMember("member");
    3. }
    To copy to clipboard, switch view to plain text mode 
    And what if I want iterate over the map and delete every instance. Which iteration should I use there? I know there is qDeleteAll, but suppose there's nothing like that.
    Last edited by QtCrawler; 18th December 2015 at 08:36.

  8. #6
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Why const can disappear at QMap::value(...)

    So I can use MyObject * object_one = myMap->value(1); and it is completely valid, although value() returns MyObject const * object_one (which is a copy of the value in the map).
    In your example the QMap<Key,T> template works out like this
    Qt Code:
    1. QMap<int, MyObject*> map;
    2. // ^ ^
    3. // | +-- T == "MyObject*"
    4. // |
    5. // +-- Key == "int"
    To copy to clipboard, switch view to plain text mode 
    The function QMap::value() returns a "const T", that is, "const MyObject*" (constant pointer-to-obj) not "MyObject const *" (pointer-to-const-obj) . In assigning that return value to a pointer variable you make a copy of it, which may or may not be const.

    Have a look at the variations in here:
    Qt Code:
    1. #include <QCoreApplication>
    2. #include <QMap>
    3.  
    4. class MyObject {
    5. public:
    6. void constFunc() const { }
    7. void nonConstFunct() { }
    8. };
    9.  
    10. int main(int argc, char **argv) {
    11. QCoreApplication app(argc, argv);
    12.  
    13. MyObject *a = new MyObject;
    14. MyObject const *b = new MyObject;
    15.  
    16. QMap<int, MyObject *> map1;
    17. map1.insert(0, a); // ok
    18. // map1.insert(1, b); // error, cannot put pointer-to-const in map
    19.  
    20. MyObject *c = map1.value(0); // ok
    21. MyObject const *d = map1.value(0); // ok
    22. c->nonConstFunct(); // ok
    23. // d->nonConstFunct(); // error, we promised d pointed to a const object
    24.  
    25. // You can have a map contain pointer-to-const-object
    26. QMap<int, MyObject const *> map2;
    27. map2.insert(0, a); // ok
    28. map2.insert(1, b); // ok
    29.  
    30. // c = map2.value(0); // error, map cannot put "MyObject const *" into a non-const pointer var
    31. d = map2.value(1); // ok
    32.  
    33. d->constFunc(); // ok, pointer-to-const and const function
    34. // d->nonConstFunct(); // error, pointer-to-const and non-const function
    35.  
    36. delete a;
    37. delete b;
    38.  
    39. return 0;
    40. }
    To copy to clipboard, switch view to plain text mode 

  9. The following 2 users say thank you to ChrisW67 for this useful post:

    d_stranz (18th December 2015), QtCrawler (18th December 2015)

  10. #7
    Join Date
    Nov 2015
    Posts
    17
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Why const can disappear at QMap::value(...)

    Ok thanks for your reply!

    I thought const MyObject* is the same as MyObject const *, so a pointer to a const MyObject. (I read it from right to left.)
    Last edited by QtCrawler; 18th December 2015 at 12:03.

  11. #8
    Join Date
    May 2015
    Posts
    66
    Thanks
    10
    Thanked 17 Times in 17 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Why const can disappear at QMap::value(...)

    Quote Originally Posted by ChrisW67 View Post
    "const MyObject*" (constant pointer-to-obj) not "MyObject const *" (pointer-to-const-obj)
    @ChrisW67 I don't think so..

    If I am not wrong, "MyObject * const" is a constant pointer-to-obj. The two things you mentioned are both pointers to const-obj.

  12. The following user says thank you to Vikram.Saralaya for this useful post:

    QtCrawler (18th December 2015)

  13. #9
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Why const can disappear at QMap::value(...)

    Quote Originally Posted by Vikram.Saralaya View Post
    @ChrisW67 I don't think so..

    If I am not wrong, "MyObject * const" is a constant pointer-to-obj. The two things you mentioned are both pointers to const-obj.
    Indeed. ChrisW67 textually substituted "T" with "MyObject*" is his otherwise perfectly exact explanation, but I am sure he meant a semantic substitution: "immutable T" -> "immutable pointer to (mutable) MyObject" aka "MyObject *const".

  14. The following 2 users say thank you to yeye_olive for this useful post:

    d_stranz (18th December 2015), QtCrawler (18th December 2015)

  15. #10
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,325
    Thanks
    316
    Thanked 871 Times in 858 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Why const can disappear at QMap::value(...)

    Even after 25+ years of C++ coding, this is one aspect that continues to confuse me. And then there are the versions with two const declarations "const MyObject const *" or whatever. Thank god for google.

  16. #11
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Why const can disappear at QMap::value(...)

    It is a strange person that does not have to think twice (i wrote the code to check myself). As yeye_olive points out, even my explanation is a little imprecise. To be clear, value() returns type MyObject* const and not const MyObject* (more clearly written MyObject const *) as a naive text substitution interpretation of templates might lead you to think.

    In my defence, it was a long week

  17. The following user says thank you to ChrisW67 for this useful post:

    QtCrawler (18th December 2015)

  18. #12
    Join Date
    Nov 2015
    Posts
    17
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Why const can disappear at QMap::value(...)

    Thank you guys.
    It's great to discuss such topics with you.
    Thank god for QtC

  19. #13
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Why const can disappear at QMap::value(...)

    Quote Originally Posted by d_stranz View Post
    Even after 25+ years of C++ coding, this is one aspect that continues to confuse me. And then there are the versions with two const declarations "const MyObject const *" or whatever. Thank god for google.
    C/C++ is quite liberal with the placement of the "const" qualifier in a declarator. IMHO it is a shame that the ambiguous form "const T *" be so prevalent. I tend to consistently place "const" after the type it qualifies, like * and &, which eliminates the ambiguous forms. All I have to do is read the declaration from right to left:
    T const: constant T
    T const *: pointer to constant T
    T * const: constant pointer to T
    T const * const: constant pointer to constant T

    If you ever are in doubt about a declaration, check out the excellent cdecl.org.

  20. The following user says thank you to yeye_olive for this useful post:

    d_stranz (19th December 2015)

Similar Threads

  1. Replies: 0
    Last Post: 22nd June 2013, 10:02
  2. screen just disappear after compiling
    By calebmakore in forum Qt Programming
    Replies: 1
    Last Post: 5th October 2011, 08:20
  3. Can't get title bar to disappear from widget
    By MattPhillips in forum Qt Programming
    Replies: 11
    Last Post: 2nd November 2010, 14:41
  4. Replies: 1
    Last Post: 4th December 2009, 17:03
  5. const member and const method
    By mickey in forum General Programming
    Replies: 8
    Last Post: 9th April 2008, 09:44

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.