Thread: preserving beyond a function

  1. #1
    Registered User
    Join Date
    May 2009
    Posts
    242

    preserving beyond a function

    In the chap. of Prata that I'm currently working on, he creates a simplified version of the string class with the name String. It allocates memory dynamically for the char array, and he shows you how to build constructor, destructor, copy constructor, assignment operator and a few others.

    Then as part of an exercise (No. 2, p. 629), you're supposed to add some things to the class he has delivered in the chapter. First, you're supposed to overload the + operator to concatenate two Strings, and that's where I'm having a scope issue.

    This is my prototype, and I think that's really the way the prototype should look:

    String & operator+(const String &) const;

    Then I tried the following implementation, which I doubted would work (and it didn't) but which seemed the only way to do it. "len" is a private member variable giving the (int) length of the array, and "str" is the private member variable holding the relevant C-string.

    Code:
    String & String::operator+(const String & st) const
    {
    	cout << "Entering operator+\n";
    	String joinSt;
    	joinSt.len = len + st.len;
    	delete [] joinSt.str;
    	joinSt.str = new char[joinSt.len + 1];
    	strcpy(joinSt.str, str);
    	joinSt.str[len] = '\0';
    	strcat(joinSt.str, st.str);
    	cout << "Still in operator+\n";
    	return joinSt;
    }
    This compiles but gives me a run-time error on a simple test program just as you leave the function, and I'm assuming it's because the joinSt variable gets destroyed as you leave the function.

    My dilemma: For the return value to exist AFTER the function is called, it has to exist BEFORE the function is called, hence be input. But + takes 2 arguments, neither of which should be changed by calling it, and it returns one value that isn't an input (or at least I'm not seeing how to preserve the proper syntax for operator+ and put in some dummy String that becomes the result).

    So, how do I keep my concatenated "String" alive outside of the operator+ function?

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    242
    It just occurred to me that since we do have functioning copy constructor and assignment operator, it might work just to make the prototype

    String operator+(const String &) const;

    I'm going to try that anyway.

  3. #3
    Registered User
    Join Date
    May 2009
    Posts
    242
    yep, that did it!

  4. #4
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Quote Originally Posted by Aisthesis
    This compiles but gives me a run-time error on a simple test program just as you leave the function, and I'm assuming it's because the joinSt variable gets destroyed as you leave the function.
    You are returning a reference, in this case it's a reference to a local object that is destructed (popped off the stack) when the function ends. You should have received some kind of warning from your compiler, something along the lines of "returning an address/reference of/to a temporary/local".
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> yep, that did it!
    There are canonical forms of the operators that you can usually look up and follow. It's great to be able to figure it out yourself and understand why they're that way, but it can help to verify your initial guess by looking up what the generally accepted prototypes are. In this case, your updated version is correct.

    However, you might also consider implementing operator+=, and then simply using the copy constructor and operator+= to implement operator+. This helps keep all the code for adding in one place and it provides you with the extra operation.

  6. #6
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    generally speaking, operators that do not perform assignment (+,-,*,/,|,&,^,~) return by value, compound assignment operators (+=,-=,*=,/=,|=,&=,^=) return *this by reference.

  7. #7
    Registered User
    Join Date
    May 2009
    Posts
    242
    to Dave: Agree on canonical forms. Is there a spot where that's all laid out, or would you suggest just writing it up myself in Word or such?

    Let me see if I follow you on the += idea (because spontaneously + seems "more primitive" to me than +=). We want st1 += st2; to mean that st1 is now the concatenation of its old self with st2 (and st2 is unchanged).

    Given that we've implemented that (which shouldn't be bad) and have a copy constructor, how do we now implement operator+? Oh, ok, that's indeed pretty easy:

    String st3(st1); // copy constructor
    st3 += st2; // operator+=

    And we're done.

    Generally, I think this problem arose really from fuzziness on what it is to return a reference.

    I'm thinking that this generalization holds: You cannot return a reference to any variable that hasn't already been created outside the function.

    I'm not seeing how there could ever be an exception to that rule.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Aisthesis View Post
    I'm thinking that this generalization holds: You cannot return a reference to any variable that hasn't already been created outside the function.
    As a rough rule, that's true.

    The real question is lifetime: the lifetime of a variable/object must be at least as long as the lifetime of any reference to that object or undefined behavior occurs.

    When phrased that way, the concept makes sense for dynamically allocated objects as well.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  2. Seg Fault in Compare Function
    By tytelizgal in forum C Programming
    Replies: 1
    Last Post: 10-25-2008, 03:06 PM
  3. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  4. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  5. const at the end of a sub routine?
    By Kleid-0 in forum C++ Programming
    Replies: 14
    Last Post: 10-23-2005, 06:44 PM