2

Based on the idea of this entry Is it a good idea to return “ const char * ” from a function?

I thought to extend this with another question I have.

Consider the following code:

#include <string>
#include <cstdio>

const char * GetSomeString() 
{ 
  std::string somestlstring;
  somestlstring = "Hello World!";

  return somestlstring.c_str(); 
}

int main()
{
  const char * tmp = GetSomeString();

  printf("%s\n", tmp);  

  return 0;
}

If I build it with

g++ source.cpp -o executable

and execute that, I get strange symbols displayed. This is because somestlstring is destroyed through the callstack and the pointer you keep after returning became invalid.

My question is: how should I design a method or function that does not have such behaviour without actually declaring additional global variables or potential member functions?

Gerhard Stein
  • 1,543
  • 13
  • 25

5 Answers5

15

You should drop the whole C mindset and start writing C++:

#include <string>
#include <iostream>

std::string GetSomeString() 
{ 
  std::string somestlstring;
  somestlstring = "Hello World!";

  return somestlstring; 
}

int main()
{
  std::string tmp = GetSomeString();

  std::cout << tmp << std::endl;

  return 0;
}
nvoigt
  • 75,013
  • 26
  • 93
  • 142
4

One obvious solution is to make the return type std::string.

Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135
3

how should I design a method or function that does not have such beahviour without actually declaring additional global variables or potential member functions?

Not at all. If you return a const char *, your function is kind of telling the caller "here you have a C string to use, but it stays mine" *), and this implies the caller doesn't have to bother releasing the resources, for example. So you can do this from an instance method (returning a pointer to a field) or you can have a function return a pointer to some static buffer (global variable).

If you want to return a dynamically allocated C string from a function, you must return char * instead and the caller has to free() it when done using it.

That all said, in C++ this doesn't make much sense, except when somehow interfacing with C code. If you want to write C++ code, go with nvoigt's answer.


*) this is thinking in terms of ownership, which is very helpful dealing with manually managed resources. The owner of something is responsible for appropriate cleanup. You can only return a const raw pointer if you don't transfer ownership of the object to the caller.

2

You are currently referencing the memory of a local std::string object which is destroyed when the object goes out of scope (when returning from the function)

if you really want to return a const char *:

  • you have to make your std::string static (but only 1 value is shared by your application)
  • or you have to duplicate the string memory (but you need to free it or you get memory leaks, like happened a lot with the old str() method of the old strstream object, which was later converted to std::string)

But as others said, better stick to C++ std::string (or const reference) as a return value and take c_str() of that returned string when needed for C-style interfaces.

std::string tmp = GetSomeString();

FILE *f = fopen(tmp.c_str(),"r");
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
0

The local string variable in the GetSomeString() function will get out of scope after you returned from the funtion. You will be printing random stuff that is in the memory position where the string was before. Try this:

#include <string>
#include <cstdio>

void GetSomeString(std::string& str) 
{
  str = "Hello World!";
}

int main()
{
  std::string str;
  GetSomeString(str);

  std::cout << str << std::endl;  

  return 0;
}
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
JOK
  • 135
  • 1
  • 7
  • Good idea, I forgot to mention that I want to avoid call by references, because this is a getter function in my eyes and should instead of read stuff into. But your solution works fine as well. – Gerhard Stein Jul 28 '17 at 08:31
  • 2
    Call this opinion, but I think that out params are extremely bad practice because of their poor readability. – Bartek Banachewicz Jul 28 '17 at 08:56
  • I have to agree Bartek Banachewicz, but still it's a solution. I also wouldn't want to use such an approach... – Gerhard Stein Jul 28 '17 at 09:24