Thread: operator[] difference of const and non-const

  1. #1
    Registered User DynV's Avatar
    Join Date
    Jul 2012
    Location
    Montreal, Canada
    Posts
    20

    operator[] difference of const and non-const

    I was reading a tutorial which have a header including operator[], of course an overload of the latter, having a version const and non-const, respectively:
    Code:
    T const & operator[] (iteratorClassName<T> const &) const;
    T & operator[] (iteratorClassName<T> const &);
    This got me wondering what's the real difference between the 2.

    ... whoah! I'm getting too tired. Anyway I'll do a follow-up poast but my question will remain the same, is there a difference in the code between the 2 beside something no-so-important like one display an error cerr << "wrong use..." and the other make a log clog << "successful...". IMHO, such case would be for where one of the 2 (const or non-const) shouldn't be used.

    Is there some cases where the content of the operator[] would be different at is core, a major difference (again between const and non-const) ?
    Than
    ks and it's ok if you don't understand, don't worry I'll come back to this.

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Compare:
    Code:
    void foo(iteratorClassName<int>& bar)
    {
    	auto n = bar[0];
    	n = 5;
    	std::cout << bar[0]; // Prints 5
    }
    
    void foo(const iteratorClassName<int>& bar)
    {
    	std::cout << bar[0]; // Prints whatever is stored in bar[0]
    }
    The first operator allows us to get the value at index n.
    The second operator allows us to modify the value at index n, but won't work if the object is const (because the operator isn't a const function).

    With the first operator, the first function won't compile.
    Without the second operator, the second function won't compile.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    ->

    Without the first operator, the second function won't compile.
    Without the second operator, the first function won't compile.

    Soma

  4. #4
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    In addition to Elysia's example, any time an iterator is created as the return value of a function, that iterator is const, because it's a temporary, and must use the const version of the operator.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by King Mir
    any time an iterator is created as the return value of a function, that iterator is const, because it's a temporary, and must use the const version of the operator.
    I don't think so. If the return type is not qualified as const, I would expect the non-const version of the operator to be invoked.

    EDIT:
    Oh wait, the iterator in question is the argument. In that case, I don't think it matters: what matters is whether the object itself is const in the given context.
    Last edited by laserlight; 07-10-2012 at 11:08 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    In addition to Elysia's example, any time an iterator is created as the return value of a function, that iterator is const, because it's a temporary, and must use the const version of the operator.
    I'm not entirely sure what you are saying, but for the sake of completeness, member functions including operators can be invoked on temporaries in that context, return value from functions, regardless of "constness".

    Soma

    Code:
    #include <iostream>
    
    struct STest
    {
        void doSomething()
        {
            std::cout << "not a constant method" << '\n';
        }
    };
    
    STest GetTester()
    {
        return(STest());
    }
    
    int main()
    {
        GetTester().doSomething();
        return(0);
    }

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Here is a fun example:
    Code:
    #include <iostream>
    
    class foo
    {
    public:
    	const foo& operator [] (int) const { std::cout << "Const operator called.\n"; return *this; }
    	foo& operator [] (int) { std::cout << "Non-const operator called.\n"; return *this; }
    };
    
    int main()
    {
    	foo bar1;
    	const foo& bar2 = bar1;
    	bar1[0];
    	bar2[0];
    	(bar1[0])[0];
    	(bar2[0])[0];
    }
    And output:
    Non-const operator called.
    Const operator called.
    Non-const operator called.
    Non-const operator called.
    Const operator called.
    Const operator called.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Here is a fun example:
    That serves only to partially explain how the compiler can be preferential, but it can work with only the `const' method.

    Remove the `const' reference stuff and the `const' method and the code will also compile.

    You need both examples to get the full picture.

    Soma

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Example 2:
    Code:
    #include <iostream>
    
    class foo
    {
    public:
    	const foo& operator [] (int) const { std::cout << "Const operator called.\n"; return *this; }
    };
    
    int main()
    {
    	foo bar1;
    	const foo& bar2 = bar1;
    	bar1[0];
    	bar2[0];
    	(bar1[0])[0];
    	(bar2[0])[0];
    }
    Output:
    Const operator called.
    Const operator called.
    Const operator called.
    Const operator called.
    Const operator called.
    Const operator called.

    And example 3 won't compile:
    Code:
    #include <iostream>
    
    class foo
    {
    public:
    	foo& operator [] (int) { std::cout << "Non-const operator called.\n"; return *this; }
    };
    
    int main()
    {
    	foo bar1;
    	const foo& bar2 = bar1;
    	bar1[0];
    	bar2[0]; // <--- error here (object is const)
    	(bar1[0])[0];
    	(bar2[0])[0]; // <--- error here (object is const)
    }
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    ^_^

    Well, leaving the error in place also works.

    And now there is a reasonably complete picture for the "OP" to peruse if he is still interested.

    Soma

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Elysia is feeling generous today
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User DynV's Avatar
    Join Date
    Jul 2012
    Location
    Montreal, Canada
    Posts
    20
    Quote Originally Posted by Elysia View Post
    Here is a fun example:
    [code]#include <iostream>

    class foo
    {
    public:
    const foo& operator [] (int) const { std::cout << "Const operator called.\n"; return *this; }
    foo& operator [] (int) { std::cout << "Non-const operator called.\n"; return *this; }
    };

    [...]
    This is exactly my point. The difference between the blocks of the 2 operator[] (const & non-const) are not-so-important.

    Are there cases where the difference is important? That the block content are fundamentally different, not just superficial differences? I have a corrected project (by a teacher) where there are 2 version of T & ClassX<T>:perator[] (int) (const & non-const) which have exactly the same block containing
    Code:
    assert(/* validation 1 */);
    assert(/* validation 2 */);
    // ...
    
    return memberT[parameterInt];
    I have a hard time thinking of an example but it could be something like.. haha I spent 15-20 minutes trying to come up with an example, I just couldn't do it.

  13. #13
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by laserlight View Post
    I don't think so. If the return type is not qualified as const, I would expect the non-const version of the operator to be invoked.

    EDIT:
    Oh wait, the iterator in question is the argument. In that case, I don't think it matters: what matters is whether the object itself is const in the given context.
    A temporary binds to a const reference, never a non-const reference. And a function that returns an iterator creates a temporary. It's also possible to create a temporary with a constructor call or cast.

    Here's an example.
    Code:
    class Obj{
    };
    
    void bar(Obj &){}
    //void bar (Obj const &){}
    
    Obj foo(){
      return Obj();
    }
    
    int main(){
      bar(foo());//error if no const operator. 
      return 0;
    }
    Member function lookup is a little different; you can call a non const method on a temporary.
    Last edited by King Mir; 07-10-2012 at 04:17 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by DynV View Post
    Are there cases where the difference is important?
    Yes, but it depends on your design.
    One operator is called with the intention that it is allowed to modify your object's state.
    The other one is called with the intention that it isn't allowed to modify your object's state.
    When taking that into account when designing your class, you may end up with different code for the paths.
    I can't think of a spontaneous example, though.

    Quote Originally Posted by King Mir View Post
    A temporary binds to a const reference, never a non-const reference.
    Well, it holds as long as you do not think of rvalue references as references, at least.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by Elysia View Post
    Well, it holds as long as you do not think of rvalue references as references, at least.
    Yeah, still getting used to those being in the language.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What is the difference between #define n 10 and const int n=10???
    By fredsilvester93 in forum C Programming
    Replies: 2
    Last Post: 11-22-2011, 12:46 PM
  2. Replies: 3
    Last Post: 11-15-2009, 04:57 AM
  3. Replies: 1
    Last Post: 04-03-2009, 08:52 AM
  4. Difference between const char * and char const *
    By explorecpp in forum C Programming
    Replies: 4
    Last Post: 08-09-2008, 04:48 AM
  5. Replies: 1
    Last Post: 06-30-2008, 09:08 AM

Tags for this Thread