Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ pointer to objects which go out of scope when function returns - why does this work?

Tags:

c++

scope

Both these calls to get_string and get_string2 return objects which go out of scope when the function returns. Shouldn't the returned object be an address in memory which goes out of scope after the function returns? This is using Visual Studio 2008. Should this always work? Why?

#include <iostream>

enum myID { SMALL, MEDIUM, LARGE };

const char* get_string(myID id) {
   switch(id){
      case SMALL: return "small";
      case MEDIUM: return "medium";
      case LARGE: return "large";
      default: return "unknown";
   }
}

const char* get_string2(myID id) {
   char* s = 0;
   switch(id){
      case SMALL:  s = "small"; return s;
      case MEDIUM: s = "medium"; return s;
      case LARGE:  s = "large"; return s;
      default: return "unknown";
   }
}

int main() {
   std::cout << get_string(SMALL) << std::endl;
   std::cout << get_string2(SMALL) << std::endl;
   return 0;
}
like image 426
Angus Comber Avatar asked May 16 '13 15:05

Angus Comber


Video Answer


1 Answers

String literals are the only literals that are lvalues and have static storage duration. So returning a pointer to the first element of a string literal is very safe. Compare

const char* f1()
{
      return "Hello"; // OK
} 

const char* f2()
{
      const char s[6] = "Hello";
      return s; // Undefined Behavior
} 


const char* f3()
{
      const char* s = "Hello";
      return s; //OK
} 

Judging from comments, this answer needs some elaboration. OK, see, a string literal is stored in the memory until the program has finished. In case 1 you return a pointer to it. The object pointer to is alive, so it's fine. In case 3, you take the address of the literal into a local variable s and return the latter by copy. The copy of the address still points to a valid memory, so it's fine. In the second case, however, we copy the string literal into a local array s which is destroyed upon function exit. Returning the address of a local variable is undefined behavior.

Further, if what you thought was undefined behavior were actually undefined then you shouldn't be surprised either because undefined behavior can mean

  • doesn't work
  • works sometimes
  • always works
  • does funny inexplicable stuff
  • anything

So if something works it doesn't mean it's OK. In this case it is, but not in the general case.

like image 194
Armen Tsirunyan Avatar answered Oct 13 '22 19:10

Armen Tsirunyan