CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 23
  1. #1
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578

    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

  2. #2
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    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

  3. #3
    Join Date
    May 2004
    Location
    Norway
    Posts
    655
    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.

  4. #4
    Join Date
    Mar 2004
    Location
    Israel
    Posts
    638
    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
    **** **** **** **** **/**

  5. #5
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    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

  6. #6
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    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

  7. #7
    Join Date
    May 2004
    Location
    Norway
    Posts
    655
    Looks like your compiler is having a bad day to me. What version are you using?

  8. #8
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    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

  9. #9
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125
    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

  10. #10
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    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

  11. #11
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,725
    reftest.cpp:12: assignment of read-only reference `ref'
    this is a correct error message. The offending line :

    Code:
    ref = 5;
    you are trying to change a CONST reference.

    you will get the same error with :

    Code:
      const int x = 1;
      x = 5;

  12. #12
    Join Date
    May 2004
    Location
    Norway
    Posts
    655
    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.

  13. #13
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    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

  14. #14
    Join Date
    Mar 2003
    Location
    Germany, K-Town
    Posts
    578
    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

  15. #15
    Join Date
    May 2004
    Location
    Norway
    Posts
    655
    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.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured