std::string gets destroyed before return

Hello, I have just implemented a few functions in a class of my program where some of them should return a std::string.

In those functions I use a temporary string to get the desired data and I return it at the end of the function. However I never get the string when I call the function, it seems to be destroyed before he returns it.

But I thought that string stays alive when it gets returned and is not being destroyed when he quits the function (or at least a copy is made)? Also I found some examples where this should work (function with a temporary string that is being returned).

Here's one of the mentioned functions I wrote:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
string Config::GetVar(char* varname)
{
	int start, end;
	string result = "";
	string searchString = varname;
	searchString.append("=");
	
	start = var_buffer.find(searchString); //var_buffer is a class variable of type string
	end = var_buffer.find_first_of('\n', start);
	
	if(start != string::npos && end != string::npos)
	{
		int actualStart = start+searchString.size();
		result = var_buffer.substr(actualStart, (end-actualStart));
	}
	return result;
}

So now my questions are, why doesn't this work and what do I need to do to make it work (as efficient as possible)?
Last edited on
Using your code but adding a class declaration and a main() with some test code as below, the result variable in Config::GetVar(...) ends up with "100" and so does the local variable named 'result' in the main():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <string>
using namespace std;

class Config
{
public:
	Config()
		: var_buffer("random data variable1=100\nvariable2=200\n")
	{
	}
	~Config(){}
	string GetVar(char*);

private:
	string var_buffer;
};

string Config::GetVar(char* varname)
{
	int start, end;
	string result = "";
	string searchString = varname;
	searchString.append("=");
	
	start = var_buffer.find(searchString); //var_buffer is a class variable of type string
	end = var_buffer.find_first_of('\n', start);
	
	if(start != string::npos && end != string::npos)
	{
		int actualStart = start+searchString.size();
		result = var_buffer.substr(actualStart, (end-actualStart));
	}
	return result;
}

int main()
{	
	Config c;
	string result = c.GetVar("variable1");

	return 0;
}
Last edited on
Ok maybe something else is the problem.

I might add that I have a pointer to Config Config* c = new Config() and that previously I didn't actually wanted to get the string from the function but its const char*.
I originally did const char* as return type and called return result.c_str(); but the result was the same as it is now so I changed it to string.

So my function calling looks like this:
const char* value = c->GetVar("variable2").c_str();
And when I do it like this, value contains an empty string.

If I do this however:
string value = c->GetVar("variable2");
then value contains the wanted value.

But either way, shouldn't the first method also work or am I missing something here?

If possible I would like to use the first method because I don't always want to create a new string and call it with .c_str() (which I would have to do a couple of times in the code).
Last edited on
Why not just use std::string everywhere?

c_str() just returns a pointer to the internal array of the std::string. If you store the pointer that is returned from c_str() you will have to be careful. If the std::string need to reallocate it's internal array or the string is destroyed the pointer will no longer be valid.
Well if you are trying to return the address of a local variable to your function, obviously this won't work as by the time the caller gets the returned result, the local variable in your function to which you are returning the address will have gone out of scope.

If you want to return an address you can either declare the result of the function in the argument list, so the variable will have been declared by the caller and passed the address through to the function. Or you could use a temporary member variable in your class. Here are both methods:

firts method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Config
{
public:
	Config()
		: var_buffer("random data variable1=100\nvariable2=200\n")
	{
	}
	~Config(){}
	void GetVar(char*, char**);

private:
	string var_buffer;
};

void Config::GetVar(char* varname, char** result)
{
	if (*result)
		delete[] *result;

	int start, end;
	string searchString = varname;
	searchString.append("=");
	
	start = var_buffer.find(searchString); //var_buffer is a class variable of type string
	end = var_buffer.find_first_of('\n', start);
	
	if(start != string::npos && end != string::npos)
	{
		int actualStart = start+searchString.size();
		string temp = var_buffer.substr(actualStart, (end-actualStart));
		*result = new char[temp.length()+1];
		strcpy(*result, temp.c_str());
	}
}

int main()
{	
	Config c;
	char* result(NULL);
	c.GetVar("variable1", &result);

	if (result)
		delete[] result;

	return 0;
}


second method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Config
{
public:
	Config()
		: var_buffer("random data variable1=100\nvariable2=200\n")
		, temp(NULL)
	{
	}

	~Config()
	{
		if (temp)
			delete[] temp;
	}

	char* GetVar(char*);

private:
	string var_buffer;
	char* temp;
};

char* Config::GetVar(char* varname)
{
	if (temp)
		delete[] temp;

	int start, end;
	string searchString = varname;
	searchString.append("=");
	
	start = var_buffer.find(searchString); //var_buffer is a class variable of type string
	end = var_buffer.find_first_of('\n', start);
	
	if(start != string::npos && end != string::npos)
	{
		int actualStart = start+searchString.size();
		string s = var_buffer.substr(actualStart, (end-actualStart));
		temp = new char[s.length()+1];
		strcpy(temp, s.c_str());
	}

	return temp;
}

int main()
{	
	Config c;
	char* result =	c.GetVar("variable1");

	return 0;
}
I see, thanks for the thorough answers, I guess I will rewrite my code a little ;-)
Topic archived. No new replies allowed.