Skip to main content
GameDev.net gamedev.net
🔒 Locked

Const references

Started by Nacho Dec 9, 2001 at 12:30 PM 22 replies 750+ views
Original Post
Nacho
Nacho
Hi! I´m reading Sams Teach Yourself C++ in 21 Days 4º Edition and I´ve got a little problem. On page 298 the author explains how to overload the increment operator using this member function: const Counter& Counter::operator++() { ++itsVal; return *this; } He explained that he declared the reference to be constant to prevent statements like this ++++i. But I don´t see what´s wrong with such statements! Ah, one more thing: Can somebody explain me what´s the difference between returning a reference and returning a constant reference? When should I use each technique? Thanks in advance!!
Shannon Barber
Shannon Barber
You make stuff const when you don''t want it to be changed...
I wouldn''t return a constant reference from operator++()...

Magmai Kai Holmlor

"Oh, like you''ve never written buggy code" - Lee

"What I see is a system that _could do anything - but currently does nothing !" - Anonymous CEO
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
AdmiralBinary
AdmiralBinary
It also prevents things like
  ++i = 5;  

Which I think would be kinda confusing...

---------------

I finally got it all together...
...and then forgot where I put it.
Oluseyi
Oluseyi
quote:
Original post by AdmiralBinary
...which I think would be kinda confusing...

...but is legal. The author goofed up big time.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
Nacho
Nacho
By the way, I am the Anonymous Poster.
Oluseyi
Oluseyi
Return a constant reference if you do not wish for the receiving instance/variable to modify the original variable. Returning a constant reference from an increment operator is silly; here''s why:
int a = 5;
int &b = ++a; // assign b to incremented a
++b; // if b was assigned a const reference, this would fail
const int &c = a;
++c; // *this* is the use that should fail

Look up ''const'' in your language reference for further information.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
DigitalDelusion
DigitalDelusion
The author is right, it''s a matter of style, and mostly you should follow the "let it behave like an int rule".
So yes you could say that ++++i should be legal but for ints it aint and thus you shouldn''t let it be possible for you own classes either.

HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Shannon Barber
Shannon Barber
quote:
Original post by DigitalDelusion
The author is right, it's a matter of style, and mostly you should follow the "let it behave like an int rule".
So yes you could say that ++++i should be legal but for ints it aint and thus you shouldn't let it be possible for you own classes either.




Try this in your favorite compiler, it works in mine...
  
#include <iostream.h>

int main(int argc, char* argv[])
{
int i=0;
++++i;
cout<<i<<endl;
return 0;
}


Magmai Kai Holmlor

"Oh, like you've never written buggy code" - Lee

"What I see is a system that _could do anything - but currently does nothing !" - Anonymous CEO

Edited by - Magmai Kai Holmlor on December 10, 2001 12:20:34 PM
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
BaShildy
BaShildy
      
#include <iostream.h>

int main(int argc, char* argv[])
{
int i=0;
++++i;
cout<<i<<endl;
return 0;
}


It works, but isn't that behavior undefined? Doing 2 pre- incraments *could* create 2 copies of the variable, each getting 1 incrament, and the first copy being thrown away. This is the reason ++i++ does not work, and if it does will not produce the intended result always.

Code comment of the week:
bool hack = false; // DO NOT CHANGE THIS EVER

Edited by - BaShildy on December 11, 2001 3:37:28 AM
Kevin "BaShildy" KingGame Programmer: DigiPenwww.mpogd.com
ed9er
ed9er
non-const for prefix-increment is OK, IMHO

quote from <thinking in C++>

quote:


The increment and decrement operators present a dilemma because of the pre- and postfix versions. Both versions change the object and so cannot treat the object as a const. The prefix version returns the value of the object after it was changed, so you expect to get back the object that was changed. Thus, with prefix you can just return *this as a reference. The postfix version is supposed to return the value before the value is changed, so you''re forced to create a separate object to represent that value and return it. So with postfix you must return by value if you want to preserve the expected meaning. (Note that you''ll sometimes find the increment and decrement operators returning an int or bool to indicate, for example, whether an object designed to move through a list is at the end of that list.) Now the question is: Should these be returned as const or nonconst? If you allow the object to be modified and someone writes (++a).func( ), func( ) will be operating on a itself, but with (a++).func( ), func( ) operates on the temporary object returned by the postfix operator++. Temporary objects are automatically const, so this would be flagged by the compiler, but for consistency''s sake it may make more sense to make them both const, as was done here. Or you may choose to make the prefix version non-const and the postfix const. Because of the variety of meanings you may want to give the increment and decrement operators, they will need to be considered on a case-by-case basis.







------------------------------
Dedicate to nobody, I''m nobody
------------------------------------------------------CCP is fascistic, they even banned www.sourceforge.net
ed9er
ed9er
i can not see anything illegal for ints

quote:
Original post by DigitalDelusion
So yes you could say that ++++i should be legal but for ints it aint and thus you shouldn''t let it be possible for you own classes either.






------------------------------
Dedicate to nobody, I''m nobody
------------------------------------------------------CCP is fascistic, they even banned www.sourceforge.net
DigitalDelusion
DigitalDelusion




int main(void)



}



int i = 0;



++++i;



}









$gcc -o test test.c



output:



test.c: In function 'main':



test.c:4: invalid lvalue in increment







thats my fav compiler...



but here comes the "fun" part

if I use g++ that is the c++ compiler it actually works

and that bothers me.



so it seems ++++ is legal c++ but illegal c and hence just confusing and shouldnt be used anyway

Edited by - DigitalDelusion on December 11, 2001 4:23:28 AM
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Beer Hunter
Beer Hunter
Even if ++++i is considered correct by the standard, I''d personally use i += 2.
Oluseyi
Oluseyi
quote:
Original post by Beer Hunter
Even if ++++i is considered correct by the standard, I''d personally use i += 2.

Definitely, unless it was an obfuscated code contest. However, what if some strange inline/macro preincremented a variable and you mistakenly increment that...

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
Shannon Barber
Shannon Barber
I think the fact that it's not legal C is where all the confusion is.

++++o on an object is definetly defined, and I think it is on an int as well. I can see concern because of the way BCB implements opreator++(int&) - but if ++++i didn't work, you couldn't ever use ++ on i in the same statement; which you can do. The behavior during execution is different in MSVC and BCB (and varies among other compilers) but after the statement, i will have the same value.

    
p = r[++i] + g[++i] + b[++i];

If it's not portable C++, is it still legal C++?

Now, o++++ has "issues".

Magmai Kai Holmlor

"Oh, like you've never written buggy code" - Lee

"What I see is a system that _could do anything - but currently does nothing !" - Anonymous CEO

Edited by - Magmai Kai Holmlor on December 11, 2001 7:24:25 PM
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Nacho
Nacho
I´m back. I had problems with my server, sorry. In my last post I asked what happen when you assign a const reference as an initialization for a new object. Here´s the source code I modified and compiled on MSVC++ 6. Can somebody explain me why "a" can be incremented if I initialize it with a constant return value?

#include

using namespace std;

class Counter
{
public:
Counter();
Counter(const Counter &rhs);
~Counter();
int GetItsVal() const { return itsVal; }
void SetItsVal(int x) { itsVal = x; }
void Increment() { ++itsVal; }
const Counter& operator++();
const Counter operator++(int);

private:
int itsVal;
};

Counter::Counter(const Counter &rhs)
{
this->itsVal = rhs.itsVal;
cout << "This is the copy constructor" << endl;
}

Counter::Counter():
itsVal(0)
{}

Counter::~Counter()
{
cout << "Destructor" << endl;
}

const Counter& Counter::operator ++()
{
++itsVal;
return *this;
}

const Counter Counter::operator ++ (int theFlag)
{
Counter temp(*this);
++itsVal;
return temp;
}

int main()
{
Counter i;
cout << "The value of i is " << i.GetItsVal() << endl;
i++;
cout << "The value of i is " << i.GetItsVal() << endl;
++i;
cout << "The value of i is " << i.GetItsVal() << endl;
Counter a = i++;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
a = i++;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
a++;
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
return 0;
}
Oluseyi
Oluseyi
Could I ask you to edit your post and trim out all the unnecessary code? I can''t stand wafting through code trying to find errors. Post only the relevant lines (variable declarations, variable initialization, function prototype, function body) and explain the context. It helps us help you faster.

Thanks.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
Nacho
Nacho
Ok,ok! I tought you were going to copy and paste my post. Here´s the relevant part:

// The overloaded operators.
const Counter& Counter::operator ++()
{
++itsVal;
return *this;
}

const Counter Counter::operator ++ (int theFlag)
{
Counter temp(*this);
++itsVal;
return temp;
}
// Something within main().
Counter a = i++;
a++; // Legal!!
cout << "The value of a: " << a.GetItsVal();
cout << " and i: " << i.GetItsVal() << endl;
return 0;
}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.