15.8 Answers to Chapter Questions

I l @ ve RuBoard

Answer 15-1: The problem is that the variable name is a temporary variable. The compiler allocates space for the name when the function is entered and reclaims the space when the function exits. The function assigns name the correct value and returns a pointer to it. However, the function is over, so name disappears and you have a pointer with an illegal value.

The solution is to declare name static. Consequently, it is a permanent variable and will not disappear at the end of the function.

If we had used the C++ string class we would not have had this problem. That's because the string class's copy constructor and memory allocation logic prevents the destruction of memory before we finish using it.

Question 15-2: After fixing the function, you try using it for two filenames. Example 15-9 should print out:

 Name: tmp1  Name: tmp2 

but it doesn't. What does it print and why?

Example 15-9. tmp2/tmp2.cpp
 #include <iostream> #include <cstring> /********************************************************  * tmp_name -- return a temporary file name             *  *                                                      *  * Each time this function is called, a new name will   *  * be returned.                                         *  *                                                      *  * Warning: There should be a warning here, but if we   *  *      put it in we would answer the question.         *  *                                                      *  * Returns                                              *  *      Pointer to the new file name.                   *  ********************************************************/ char *tmp_name(  ) {     static char name[30];       // The name we are generating     static int sequence = 0;    // Sequence number for last digit      ++sequence; // Move to the next file name     strcpy(name, "tmp");     // But in the squence digit      name[3] = static_cast<char>(sequence + '0');     // End the string      name[4] = ' 
 #include < iostream > #include <cstring> /******************************************************** * tmp_name -- return a temporary file name * * * * Each time this function is called, a new name will * * be returned. * * * * Warning: There should be a warning here, but if we * * put it in we would answer the question. * * * * Returns * * Pointer to the new file name. * ********************************************************/ char *tmp_name( ) { static char name[30]; // The name we are generating static int sequence = 0; // Sequence number for last digit ++sequence; // Move to the next file name strcpy (name, "tmp"); // But in the squence digit name[3] = static_cast<char>(sequence + '0'); // End the string name[4] = '\0'; return(name); } int main( ) { char *name1; // name of a temporary file char *name2; // name of a temporary file name1 = tmp_name( ); name2 = tmp_name( ); std::cout <<"Name1: " << name1 << '\n'; std::cout <<"Name2: " << name2 << '\n'; return(0); } 
'; return(name); } int main( ) { char *name1; // name of a temporary file char *name2; // name of a temporary file name1 = tmp_name( ); name2 = tmp_name( ); std::cout <<"Name1: " << name1 << '\n'; std::cout <<"Name2: " << name2 << '\n'; return(0); }

The first call to tmp_name returns a pointer to name . There is only one name . The second call to tmp_name changes name and returns a pointer to it. So you have two pointers, and they point to the same thing, name .

Several library functions return pointers to static strings. A second call to one of these routines will overwrite the first value. A solution to this problem is to copy the values:

 char name1[100];  char name2[100];  strncpy(name1, tmp_name(  ), sizeof(name1));  strncpy(name2, tmp_name(  ), sizeof(name1)); 

OK, we decided to finally give up on C-style strings and enter the 21st century. So we've rewritten our function to use the C++ string class. Yet it still doesn't work. Why?

Example 15-10. tmp3/tmp3.cpp
 #include <iostream> #include <string> /********************************************************  * tmp_name -- return a temporary file name             *  *                                                      *  * Each time this function is called, a new name will   *  * be returned.                                         *  *                                                      *  * Returns                                              *  *      String containing the name.                     *  ********************************************************/ std::string& tmp_name(  ) {     std::string name;   // The name we are generating     static int sequence = 0;    // Sequence number for last digit      ++sequence; // Move to the next file name     name = "tmp";     // Put in the squence digit      name += static_cast<char>(sequence + '0');     return(name); } int main(  ) {     std::string name1 = tmp_name(  );     std::cout <<"Name1: " << name1 << '\n';     return(0); } 

The function returns a reference to name , which is a local variable. The problem is that C++ destroys the variable name at the end of the function. It then returns a reference to the variable (which just got destroyed ), and that's what's assigned to name1.

You should never return references to local variables or parameters unless they are declared static .

I l @ ve RuBoard


Practical C++ Programming
Practical C Programming, 3rd Edition
ISBN: 1565923065
EAN: 2147483647
Year: 2003
Pages: 364

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net