Question about references in functions

This is a discussion on Question about references in functions within the C++ Programming forums, part of the General Programming Boards category; When you have a function that returns a reference to a private member in a class, I noticed it compiles ...

  1. #1
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827

    Question Question about references in functions

    When you have a function that returns a reference to a private member in a class, I noticed it compiles fine without explicitly creating a reference to said member of class.
    If I do, for example:

    Code:
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class aClass {
      public:
        const string& returnString();
      private:
        string exampleStr;
    };
    
    const string& aClass::returnString() {
    
      exampleStr = "anExampleStr";
      return exampleStr;
    
    }
    
    int main() {
    
      aClass object;
      cout<< "Example string is: " << object.returnString() <<endl;
      cout<< "\n\nPress Enter to end this program." <<endl;
      cin.get();
    
      return 0;
    
    }
    and return a string and not actually a reference (at least not a reference explicitly defined), it will still compile and give me the content of the exampleStr. Why is that?

    Why don't I have to do this:

    Code:
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class aClass {
      public:
        const string& returnString();
      private:
        string exampleStr;
    };
    
    const string& aClass::returnString() {
    
      exampleStr = "anExampleStr";
      const string& rExampleStr = exampleStr; //get a reference to the string member
      return rExampleStr; //return the reference
    
    }
    
    int main() {
    
      aClass object;
      cout<< "Example string is: " << object.returnString() <<endl;
      cout<< "\n\nPress Enter to end this program." <<endl;
      cin.get();
    
      return 0;
    
    }
    and explicitly return a reference to the private string member?

  2. #2
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,548
    The compiler is creating a temporary in your first example and returns that temporary which is a reference to said object.
    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
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    The compiler is creating a temporary in your first example and returns that temporary which is a reference to said object.
    So I suppose the second method is better than?
    But I still don't get why you can return a string object directly from a function which is supposed to return a reference.

  4. #4
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,548
    No, I'd prefer the first since it's less code.
    Re:2: Again, because of an implicit conversion.
    For example, try this code:
    Code:
    #include <iostream>
    #include <string>
    
    std::string foo()
    {
        return "Hello World!\n";
    }
    
    int main()
    {
        std::cout << foo();
    }
    It works on the same principle.
    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.

  5. #5
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    No, I'd prefer the first since it's less code.
    Re:2: Again, because of an implicit conversion.
    For example, try this code:
    Code:
    #include <iostream>
    #include <string>
    
    std::string foo()
    {
        return "Hello World!\n";
    }
    
    int main()
    {
        std::cout << foo();
    }
    It works on the same principle.
    Sorry, I meant the first (i.e. the one that returns a string directly, and doesn't explicitly create a reference inside the function).
    So, when you use a second method, does it make any difference that the reference is local to the function and not a member of the class?
    And when you assign a string object the returning value of a function that returns a reference to a string (which in the code, looks like its returning the string object directly), does the assigned string get a copy of what's being referenced?

  6. #6
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,548
    Quote Originally Posted by Programmer_P View Post
    So, when you use a second method, does it make any difference that the reference is local to the function and not a member of the class?
    Yes. A reference does not create an additional object; it's merely an alias for an existing object. If the object is local, then it will go out of scope and the reference become invalid. Hence undefined behavior. This cannot happen with member variables so long as the object itself is valid.

    And when you assign a string object the returning value of a function that returns a reference to a string (which in the code, looks like its returning the string object directly), does the assigned string get a copy of what's being referenced?
    I can't make sense of this. Can you reword your question?
    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.

  7. #7
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    I can't make sense of this. Can you reword your question?
    Like this:

    Code:
    aClass object;
    string str = object.returnString(); //does this string being assigned the return value of the function which returns a reference get a copy of the string which is being referenced?
    I'm guessing it does, but I just wanted to ask to make sure. And how faster is that compared to if I were do the same thing, only with the function returning the string itself, and not a reference to it?

  8. #8
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,548
    Since str is not a reference, yes. A copy will be made and stored in str.
    The good thing about returning references is 1) they eliminate temporary copies (only a reference has to be created, which is cheap) and 2) it's possible to create a non-const reference in the function which receives the return value.
    Though the standard say it is possible to do
    Code:
    int foo() { return 0; }
    int main() { const int& n = foo(); }
    You cannot do:
    Code:
    int foo() { return 0; }
    int main() { int& n = foo(); }
    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.

  9. #9
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    Since str is not a reference, yes. A copy will be made and stored in str.
    The good thing about returning references is 1) they eliminate temporary copies (only a reference has to be created, which is cheap) and 2) it's possible to create a non-const reference in the function which receives the return value.
    Though the standard say it is possible to do
    Code:
    int foo() { return 0; }
    int main() { const int& n = foo(); }
    You cannot do:
    Code:
    int foo() { return 0; }
    int main() { int& n = foo(); }
    Why can't you do the second one? And I thought you said its possible to create a non-const reference in the function which receives the return value? Then you just contradicted it with your code.
    And I once tried to assign a reference in the receiving function the return value of a function which returned a reference, but it didn't compile. I guess that's illegal?
    Last edited by Programmer_P; 06-08-2010 at 07:04 AM.

  10. #10
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,548
    Not exactly. Consider this code:
    Code:
    int & foo(int & r)
    {
    	return r;
    }
    
    int foo()
    {
    	return 0;
    }
    
    int main()
    {
    	int n = 0;
    	int & r1 = foo(n);
    	const int & r2 = foo(n);
    	int & r3 = foo();
    	const int & r4 = foo();
    }
    Which of the lines in main will 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.

  11. #11
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    Not exactly. Consider this code:
    Code:
    int & foo(int & r)
    {
    	return r;
    }
    
    int foo()
    {
    	return 0;
    }
    
    int main()
    {
    	int n = 0;
    	int & r1 = foo(n);
    	const int & r2 = foo(n);
    	int & r3 = foo();
    	const int & r4 = foo();
    }
    Which of the lines in main will compile?
    All but the line that says:
    Code:
    int & r3 = foo();
    The compiler complains that 'r3' is not const.
    So basically, you can not assign a non-const reference to a non-const reference? You have to make the assigned reference a const reference?

    Why is this?

    Also, earlier you said quite the opposite: it's possible to create a non-const reference in the function which receives the return value. Which you obviously did with 'r1', but the difference with the two functions is, one receives a reference to an int already in existence, and the other one returns a reference to a local value, which is probably why it doesn't work...
    But, still, with the other one, if you change 'r3' to const, it compiles without any errors, even though it seems to be referencing a local value to the 'foo()' function.

  12. #12
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,548
    You cannot assign a temporary to a non-const reference. The second foo returns a temporary int, which is not a reference. Therefore it doesn't work. Why exactly the standard mandates this I am unsure, but there you go.

    As for the second question: you must be careful with your terminology here. The first foo returns a reference. Indeed, it returns a reference to the parameter it received. I could return a reference to something else, like a global variable. So long as it isn't a local variable.
    The second function does NOT return a reference whatsoever. It returns a temporary. Therefore the 3rd line doesn't work.

    Now, if you want to go to your original question, try this code:
    Code:
    #include <iostream>
    
    class bar 
    {
    public:
    	bar() {}
    	bar(const bar&) { std::cout << "Copying me!\n"; }
    };
    
    bar & foo(bar & r)
    {
    	return r;
    }
    
    bar foo()
    {
    	return bar();
    }
    
    int main()
    {
    	bar n;
    	bar & r1 = foo(n);
    	const bar & r2 = foo(n);
    	const bar & r4 = foo();
    	
    	bar v1 = foo(n);
    	const bar v2 = foo(n);
    	bar v3 = foo();
    	const bar v4 = foo();
    }
    Which lines will create a copy? If you're unsure, comment out lines one-by-one and run the code and see if you get a "Copying me!" output.
    Last edited by Elysia; 06-08-2010 at 07:23 AM.
    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.

  13. #13
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    You cannot assign a temporary to a non-const reference. The second foo returns a temporary int, which is not a reference. Therefore it doesn't work. Why exactly the standard mandates this I am unsure, but there you go.

    As for the second question: you must be careful with your terminology here. The first foo returns a reference. Indeed, it returns a reference to the parameter it received. I could return a reference to something else, like a global variable. So long as it isn't a local variable.
    The second function does NOT return a reference whatsoever. It returns a temporary. Therefore the 3rd line doesn't work.
    Right. I knew that, and understood the code.
    I just used the wrong terminology.
    I meant the second foo() returns a local value 0, which in int main(), you attempted to get a non-const reference to it, which didn't work. You have to change it to const.
    But I still don't get why that works at all.
    What happens if you try to output the const reference to the second foo return value?
    I'm going to try that now.

    EDIT: Hmm...ok, obviously the variable local to the second foo() is still in existence, because it outputs 0. Does the 'const' keyword make the variable stay in memory longer, by any chance? I thought all it did was make the variable unable to change values.
    Last edited by Programmer_P; 06-08-2010 at 07:28 AM.

  14. #14
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Wow, this thread is full of misunderstandings.

    So, start from scratch.

    A reference is an alias for an object. If the object doesn't live as long as all references to it, those references become invalid and accessing them is undefined behavior. (Note that UB doesn't necessarily mean crash, unfortunately. Often it will appear to work, until your code becomes a little more complex.)

    References must be initialized. That is, it is an error to write:
    Code:
    int &i; // error: missing initializer
    A valid initializer for a reference is any lvalue expression of a compatible type. For example, valid initializers are variable accesses, function calls returning references, and pointer dereferences.
    Code:
    int &fn();
    void f(int *p) {
      int &r1 = fn();
      int i;
      int &r2 = i;
      int &r3 = *p;
    }
    In addition, const references can be initialized with a temporary of a compatible type. In this case, the lifetime of the temporary is extended to match the reference. Temporaries are usually the result of explicit constructor calls and of function calls returning by value. Literals can also be temporaries, but that's a rather academic case, because in the real world you don't write such code.
    Code:
    int fn();
    void f() {
      const int &r1 = fn();
      const int &r2 = 10;
    }
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Functions Question
    By audinue in forum C Programming
    Replies: 2
    Last Post: 01-09-2009, 08:39 AM
  2. newb question about interpreting and writing functions
    By crazychile in forum C Programming
    Replies: 1
    Last Post: 10-23-2008, 07:51 PM
  3. Functions and Strings Question
    By StrikeMech in forum C Programming
    Replies: 4
    Last Post: 07-18-2007, 06:07 AM
  4. question about c functions
    By LowLife in forum C Programming
    Replies: 1
    Last Post: 11-16-2005, 11:20 AM
  5. .h and functions question
    By Mick D in forum C++ Programming
    Replies: 5
    Last Post: 10-21-2005, 12:53 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21