36

I have tested this code:

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

int main()
{
    string s1("a"),s2("b");
    const char * s = (s1+s2).c_str();
    printf("%s\n",s);
}

It returns "ab".

As far as I know, since (s1 +s2) is a temporary object and may disappear somehow (I have no idea about that), then const char * s may point to undefined memory and may get dumped.

So is it safe to use the .c_str() like that?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sayakiss
  • 6,878
  • 8
  • 61
  • 107
  • 1
    Insert `string s3("Oh no!");` just before the printf, chances are your output will change. (But that's not guaranteed.) – Mat Aug 09 '13 at 12:09
  • 4
    The "possible duplicate" is fundamentally different (use within the same full expression) – MSalters Aug 09 '13 at 12:09

4 Answers4

57

It's not safe in your example. It's safe however in

printf("%s\n", (a + b).c_str());

The reason is that temporary values (like the result of a + b) are destroyed at the end of the full expression. In your example the const char * survives the full expression containing the temporary and dereferencing it is undefined behaviour.

The worst part of "undefined behaviour" is that things may apparently work anyway... (UB code crashes only if you're making your demo in front of a vast audience that includes your parents ;-) )

6502
  • 112,025
  • 15
  • 165
  • 265
29

In that example we can just quote the standard:

12.2 Temporary objects [class.temporary]

Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception. The value computations and side effects of destroying a temporary object are associated only with the full-expression, not with any specific subexpression.

That is after the semicolon of your line:

const char * s = (s1+s2).c_str(); // <- Here

So here:

printf("%s\n",s); // This line will now cause undefined behaviour.

Why? Because as your object is destructed, you don't know anymore what is at this place now...

The bad thing here is that, with Undefined behaviour, your program may seem to work at the first time, but... It will crash for sure at the worst time...

You can do:

printf( "%s\n", (s1+s2).c_str() );

It will work because the object is not destructed yet (remember, after the semicolon...).

Community
  • 1
  • 1
Pierre Fourgeaud
  • 14,290
  • 1
  • 38
  • 62
5

It's not safe, but you can easily assign to a new variable, and the pointer will be safe in the scope of that variable:

string s1("a"), s2("b") , s3;
s3 = s1 + s2;
printf("%s\n", s3.c_str());

//other operations with s3
Miguel Prz
  • 13,718
  • 29
  • 42
4

Like most programming constructs, it's "safe" if you use it correctly, and it's not "safe" if you're sloppy. In this case, using it correctly means paying attention to object lifetimes. The + operator creates a temporary object which gets destroyed at the end of the statement, and the returned const char* is no longer valid after the statement that created it. So you can pass the result of c_str() directly to a function, but you can't save the pointer and use it later.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165