|
-
May 9th, 2004, 02:22 PM
#1
const references? I'm confused.
Hey again,
I've just read something very confusing in Stroustrups book about so called const references after running into this "problem":
Consider a class C like this:
Code:
class C
{
std::string str;
public:
C() { str = "original"; }
const std::string & GetStr() const { return str; }
};
and a program, maybe like this:
Code:
C c;
std::string & ref = c.GetStr();
ref = "changed!";
cout << c.GetStr() << endl;
The output is "original". Frankly I would have expected that ref would change the value of C's data member but it doesn't. And it's not because str is const, because it isn't!
The passage about const references in Stroustrup's is somewhat vague... From what I've understood, a reference to a temporary object is returned instead of a reference to the data member itself, therefore ref = "changed" will not change the member but the temp var. However, when I leave the method's scope that temp var would be removed from the stack, so how can I still have a valid reference to it?!
Can someone explain this problem a little more in detail?
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
May 9th, 2004, 02:27 PM
#2
For further confusion, consider this:
Code:
const int & ref = 1;
No that's not a typo, that's valid C++ code. But very strange indeed!
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
May 9th, 2004, 02:59 PM
#3
Did that first example compile at all? It shouldn't, and doesn't on my compiler. You're assigning a const reference to a non-const reference, and that's illegal.
EDIT: typo.
Last edited by wien; May 9th, 2004 at 03:05 PM.
-
May 9th, 2004, 02:59 PM
#4
I'll try to make things clear about reference-
your first code cannot be compiled. you can't return a const
reference to a non const reference, so:
const std::string & GetStr()
cannot return a type to other than const string& var.
std::string & ref = c.GetStr() -----> ref is not const!!
indeed, in your code, when str is been returned,
a temporary const object is returned, but you shouldn't care
about it, since you, the programmer, declared that GetStr()
will return a value that can't be change (const, remember? ) -
so its not your business if the compiler use a temporary object or not.
about the second post:
const int & ref = 1;
yeah it seems at the first time a little weird, but thats how it is.
the only case that a const reference variable can be initialized -
its when it been declared.
Regards,
Guy
**** **** **** **** **/**
-
May 10th, 2004, 12:22 AM
#5
To both of you:
It compiles with g++ with -Wall, -pedantic and -ansi set.
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
May 10th, 2004, 09:08 AM
#6
Well, actually it produces a warning, but still compiles. For reference, I have posted my demo code as well as my makefile code with the compiler call:
source:
Code:
class C
{
int a;
public:
const int & Get() const { return a; };
};
int main()
{
C c;
int & ref = c.Get();
ref = 5;
return 0;
}
Makefile:
Code:
## makro definitions
CC = g++
DEBUG = -g
#CFLAGS = -Wall -pedantic -ansi -c $(DEBUG)
LFLAGS = -Wall -pedantic -ansi $(DEBUG)
LIBS =
OBJECTS = reftest.cpp
EXE = reftest
## makefile targets
$(EXE): $(OBJECTS)
$(CC) $(LIBS) $(LFLAGS) $(OBJECTS) -o $@
all: start $(EXE) finish
clean:
@rm -f $(EXE)
@rm -f *.o
@rm -f *~
@echo "Clean sweep!"
start:
@echo ""
@echo "Compiling $(EXE)..."
@echo ""
finish:
@echo ""
@echo "...success!"
Output:
Code:
Compiling reftest...
g++ -Wall -pedantic -ansi -g reftest.cpp -o reftest
reftest.cpp: In function `int main()':
reftest.cpp:11: warning: conversion from `const int' to `int &' discards qualifiers
...success!
Compilation finished at Mon May 10 16:01:58
No error, just a warning. Okay, now here is what happens if I change ref to be a const reference (!):
Code:
Compiling reftest...
g++ -Wall -pedantic -ansi -g reftest.cpp -o reftest
reftest.cpp: In function `int main()':
reftest.cpp:12: assignment of read-only reference `ref'
make: *** [reftest] Error 1
Compilation exited abnormally with code 2 at Mon May 10 16:06:07
So much about code only compiling when changing ref to const int & ^^
Last edited by matthias_k; May 10th, 2004 at 09:11 AM.
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
May 10th, 2004, 09:11 AM
#7
Looks like your compiler is having a bad day to me. What version are you using?
-
May 10th, 2004, 09:16 AM
#8
Originally posted by wien
Looks like your compiler is having a bad day to me. What version are you using?
2.95.4
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
May 10th, 2004, 09:17 AM
#9
reftest.cpp:11: warning: conversion from `const int' to `int &' discards qualifiers
This is a SERIOUS warning. Just because something is a warning and not an error does not mean it is ok to leave it.
MOST professional shops prohibit the "checking-in" of any production code that contains warnings.
Once I am past the very early stages of implementation I typically set my build environment to treat ALL warnings as errors.
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
May 10th, 2004, 09:20 AM
#10
Originally posted by TheCPUWizard
This is a SERIOUS warning. Just because something is a warning and not an error does not mean it is ok to leave it.
MOST professional shops prohibit the "checking-in" of any production code that contains warnings.
Once I am past the very early stages of implementation I typically set my build environment to treat ALL warnings as errors.
True, but that's not the point. The point is that changing ref to be of type const int & produces an error, which is sort of NOT logical to me.
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
May 10th, 2004, 09:21 AM
#11
reftest.cpp:12: assignment of read-only reference `ref'
this is a correct error message. The offending line :
you are trying to change a CONST reference.
you will get the same error with :
Code:
const int x = 1;
x = 5;
-
May 10th, 2004, 09:23 AM
#12
Bleh... Sorry. There is nothing wrong with what your compiler is telling you. The reason the second example fails is the line ref=5. You are assigning a value to a const variable, and that's not allowed. Remove that line and you'll be fine.
-
May 10th, 2004, 09:29 AM
#13
Oh. Right. I somewhat looked in the wrong place I guess Okay....
Great, so we can get back to my original question:
If I hand out a const reference with a getter method, and if that const reference is actually a reference to a copy of the original object, how can I still be able to have a reference to it when I leave the scope of the method (consider that the temp object is removed from the stack once I leave the scope of the getter)?
edit: At least that's what Stroustrup says in his C++ reference in fact that creating a const reference to an object will create a copy of that object and the *copy* will be referenced. That way you cant change the original object, which "simulates" a constant value (but actually isnt).
Last edited by matthias_k; May 10th, 2004 at 09:34 AM.
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
May 10th, 2004, 09:44 AM
#14
Maybe there's an internal reference counter which keeps track of objects which are still referenced and keeps them alive as long as there are references to it? I don't believe there's a mechanism like this in C++... So why does it work (remember, the first example produced a warning but I could use the reference across the whole program)?
- Matthias
"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." - Bjarne Stroustrup
-
May 10th, 2004, 09:50 AM
#15
I think the reason it "works" in your case, is by the magic of "undefined behaviour". You can't use an object beyond it's scope. (Which is in fact what you're trying to do.) Simply create a copy of it if you need to do that.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|