Thread: using references (need help)

  1. #1
    Registered User
    Join Date
    Dec 2009
    Posts
    30

    Question using references (need help)

    I am going through my C++ book and one of the exercises asks you to alter an earlier project using references (to make it more efficient). I have written the program (see below), but when I run the executable, I get a run-time error. Basically the program crashes when it's supposed to tell you a story using all the user input.

    I think that it might be a scoping problem...but i'm going through my book to check...


    All changes I made are in bold...adding references is the only change.

    Code:
    //Creates a story based on user input
    
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    string& askText(string prompt);
    int& askNumber(string prompt);
    void tellStory(string& name, string& noun, int& number, string& bodyPart, string& verb);
    
    int main()
    {
        cout << "Welcome to Mad Lib.\n\n";
        cout << "Answer the following questions to help create a new story.\n";
        
        string& name = askText("Please enter a name: ");
        string& noun = askText("Please enter a plural noun: ");
        int& number = askNumber("Please enter a number: ");
        string& bodyPart = askText("Please enter a body part: ");
        string& verb = askText("Please enter a verb: ");
        
        tellStory(name, noun, number, bodyPart, verb);
        
        cin.get();
        
        return 0;
    }
    
    string& askText(string prompt)
    {
        string text;
        cout << prompt;
        cin >> text;
        cin.ignore();
        
        string& rText = text;
        
        return rText;
    }
    
    int& askNumber(string prompt)
    {
        int num;
        cout << prompt;
        cin >> num;
        cin.ignore();
        
        int& rNum = num;
        
        return rNum;
    }
    
    void tellStory(string& name, string& noun, int& number, string& bodyPart, string& verb)
    {
        cout << "\nHere's your story:\n";
        cout << "The famous explorer ";
        cout << name;
        cout << " had nearly given up a life-long quest to fine\n";
        cout << "The Lost City of ";
        cout << noun;
        cout << " when one day, the ";
        cout << noun;
        cout << " found the explorer.\n";
        cout << "Surrounded by ";
        cout << number;
        cout << " " << noun;
        cout << ", a tear came to ";
        cout << name << "'s ";
        cout << bodyPart << ".\n";
        cout << "After all this time, the quest was finally over. ";
        cout << "And then the ";
        cout << noun << "\n";
        cout << "promplty devoured ";
        cout << name << ". ";
        cout << "The moral of the story?  Be carful what you ";
        cout << verb;
        cout << " for.";
    }

    If you have any questions regarding the code, please ask. I should be at my computer for a few more hours trying to fix this program. Any helpful advice is welcome, thanks again!
    Last edited by dhardin; 12-29-2009 at 01:35 PM. Reason: added bold text

  2. #2
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Your functions are returning references to local variables which disappear when the functions return. Either make the local variables static (not a great idea), or return them by value.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  3. #3
    Registered User
    Join Date
    Dec 2009
    Posts
    30
    So instead of having my functions return a reference, I can just return a value? But what about my original initialization of the variables name, noun, number, bodypart, and verb? I have tried to return
    the function by value but it gives my a compile error.

    Either make the local variables static (not a great idea)
    I wont be able to create static variables because I have not learned about them yet. Is static the same as global?

    New code:

    Code:
    //Creates a story based on user input
    
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    string askText(string prompt);
    int askNumber(string prompt);
    void tellStory(string& name, string& noun, int& number, string& bodyPart, string& verb);
    
    int main()
    {
        cout << "Welcome to Mad Lib.\n\n";
        cout << "Answer the following questions to help create a new story.\n";
        
        string& name = askText("Please enter a name: ");
        string& noun = askText("Please enter a plural noun: ");
        int& number = askNumber("Please enter a number: ");
        string& bodyPart = askText("Please enter a body part: ");
        string& verb = askText("Please enter a verb: ");
        
        tellStory(name, noun, number, bodyPart, verb);
        
        cin.get();
        
        return 0;
    }
    
    string askText(string prompt)
    {
        string text;
        cout << prompt;
        cin >> text;
        cin.ignore();
        
        return text;
    }
    
    int askNumber(string prompt)
    {
        int num;
        cout << prompt;
        cin >> num;
        cin.ignore();
        
        return num;
    }
    
    void tellStory(string& name, string& noun, int& number, string& bodyPart, string& verb)
    {
        cout << "\nHere's your story:\n";
        cout << "The famous explorer ";
        cout << name;
        cout << " had nearly given up a life-long quest to fine\n";
        cout << "The Lost City of ";
        cout << noun;
        cout << " when one day, the ";
        cout << noun;
        cout << " found the explorer.\n";
        cout << "Surrounded by ";
        cout << number;
        cout << " " << noun;
        cout << ", a tear came to ";
        cout << name << "'s ";
        cout << bodyPart << ".\n";
        cout << "After all this time, the quest was finally over. ";
        cout << "And then the ";
        cout << noun << "\n";
        cout << "promplty devoured ";
        cout << name << ". ";
        cout << "The moral of the story?  Be carful what you ";
        cout << verb;
        cout << " for.";
    }
    Last edited by dhardin; 12-29-2009 at 01:58 PM.

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    [edit] This post only applies to the first bunch of code. You guys type too fast. [/edit]

    You can't return references to local variables. You're trying to do this in several places, such as this:
    Code:
    string& askText(string prompt)
    {
        string text;
        cout << prompt;
        cin >> text;
        cin.ignore();
        
        string& rText = text;
        
        return rText;
    }
    I'll simplify the code to this, which is equivalent:
    Code:
    string& askText(string prompt)
    {
        string text;
        cout << prompt;
        cin >> text;
        cin.ignore();
        
        return text;
    }
    What you're doing is declaring a local variable text on the stack. (All "automatic" variables take up space on the stack this way.) You read some data into it, then return a reference to this variable. The trouble is, as soon as the function returns, its stack frame gets "destroyed" and any local variables cease to exist (go out of scope, as you suspected). Unfortunately, in many cases you can still access such local variables without the program seeming to crash (until you use that stack space again, by calling another function, at which point the variable will be overwritten). But it's still an error, and if your program relies on such behaviour, it could crash at any time.

    Looking through your code, I don't see any place where you actually need to use references. If you remove all of the references, it should work just fine. There are a few places where you can use references, though: mostly as parameters to functions.

    Let me step back a bit and say what a reference is: it's just another name for the same variable at the same location in memory. So when you pass a reference parameter to a function, all you're doing is reusing the same variable that is located in the calling function. This is good for many reasons: it saves on copying the variable (because you're just reusing it), and it allows the called function to make changes to the variable that will be reflected in the calling function. (If you don't want this to happen, you can probably pass a constant reference: e.g. "const string &name".)

    But don't try to return references to local variables, nor store the results in references in the calling function. It won't work very well . . . .
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    The only problem with your new code is that you still have references to the returned values of functions. Code like this
    Code:
        string& name = askText("Please enter a name: ");
    should be
    Code:
        string name = askText("Please enter a name: ");
    because again, a reference to a returned value doesn't make sense. (In this case.)
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  6. #6
    Registered User
    Join Date
    Dec 2009
    Posts
    30
    Okay, so it was the scoping issue....but the book exercise does require me to use references somewhere....

    I know I have to use them in the tellStory parameters, but wouldn't I have to pass references as arguments into this function? My compiler keeps giving me inizialization errors when i'm declaring the reference values of noun, verb, name, bodyPart, and number.

  7. #7
    Registered User
    Join Date
    Dec 2009
    Posts
    30
    Well, I took out the references to the returned values of functions and just passed the values as references into my tellStory function. AND IT WORKS!!! So thank you! I will have to read into it a little more to understand why the book would want me just to do that little change to the program (ugh..). But thanks again! I will be going on to the next chapter (pointers) and will have some new questions later today.

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Food for thought: one of the main reasons for references is to allow you to pass in parameters which the function is going to change. For example:
    Code:
    void swap(int &one, int &two) {
        int temp = one;
        one = two;
        two = temp;
    }
    That would be hard to write without references (or pointers).
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  9. #9
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    What you can do is this:
    Code:
        const string& name = askText("Please enter a name: ");
    with askText still returning by value of course. It is only allowed to bind temporaries (which is what the return value is) to const references, not non-const references.
    This is potentially more efficient than declaring name as a string because it may then avoid the need to copy the returned string data.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    The places where you could use references (const to indicate that you are not going to modify the arguments) are here:

    Code:
    string askText(const string& prompt);
    int askNumber(const string& prompt);
    void tellStory(const string& name, const string& noun, int number, const string& bodyPart, const string& verb);
    Also note that there is not much point in passing primitive types like ints by reference for performance reasons only.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. VC++ 2005 Express: missing references page
    By psychopath in forum Tech Board
    Replies: 1
    Last Post: 08-21-2006, 04:55 PM
  2. Arrays of references
    By Welshy in forum C++ Programming
    Replies: 16
    Last Post: 07-04-2005, 11:28 PM
  3. Vector of references
    By roktsyntst in forum C++ Programming
    Replies: 5
    Last Post: 04-15-2003, 06:40 PM
  4. declare references to references works!
    By ManuelH in forum C++ Programming
    Replies: 4
    Last Post: 01-20-2003, 08:14 AM
  5. Pointers and references...
    By SushiFugu in forum C++ Programming
    Replies: 6
    Last Post: 12-08-2001, 04:21 PM