Lifetime of temporaries?

J

Jorgen Grahn

I should know this, but ...

Is this code safe?

std::string foo();
std::printf("%s", foo().c_str());

Or is my temporary std::string destroyed before printf()
is done with it?

Background:

I'm sitting with a whole bunch of classes and (for now) only a
printf-like interface for printing logs/debug info. I was thinking
about

- implementing ostream << foo as usual,

- have a 'template<T> std:string to_string(const T&)' based on it

- log using the slightly ugly syntax
log("error in %s: %s",
to_string(foo).c_str(),
to_string(bar).c_str());

It's ugly and extremely wasteful, but I want to define the output
format in *one* place for each class -- not in every place where I might
want to print it.

/Jorgen
 
V

Victor Bazarov

Jorgen said:
I should know this, but ...

Is this code safe?

You need to define "safe". I am not certain it's a standard term.
std::string foo();

OK, 'foo' is a function returing a string.
std::printf("%s", foo().c_str());

This is an expression statement, a function call to 'std::printf' with
two arguments. The temporary returned by 'foo' lives until the end of
the full expression (here: the semicolon). The pointer 'c_str' returns
*also* lives as long as the [temporary] object that has produced it.
Or is my temporary std::string destroyed before printf()
is done with it?

'printf' doesn't actually do anything with your temporary. It needs the
pointer your temporary returns. And actually the pointer can live less
than the temporary...
Background:

I'm sitting with a whole bunch of classes and (for now) only a
printf-like interface for printing logs/debug info. I was thinking
about

- implementing ostream << foo as usual,

- have a 'template<T> std:string to_string(const T&)' based on it

- log using the slightly ugly syntax
log("error in %s: %s",
to_string(foo).c_str(),
to_string(bar).c_str());

It's ugly and extremely wasteful, but I want to define the output
format in *one* place for each class -- not in every place where I might
want to print it.

Seems like you're on your way to a satisfactory solution.

Good luck!

V
 
B

Balog Pal

Jorgen Grahn said:
I should know this, but ...

Is this code safe?

std::string foo();
std::printf("%s", foo().c_str());
Or is my temporary std::string destroyed before printf()
is done with it?

Temporaries are destroyed at end of the *full-expression*, that mean at the
; after the printf call. This use is okay, the problematis would be to call
some other function taking the const char * and save a copy of it for later
use.
- have a 'template<T> std:string to_string(const T&)' based on it

- log using the slightly ugly syntax
log("error in %s: %s",
to_string(foo).c_str(),
to_string(bar).c_str());

It's ugly and extremely wasteful, but I want to define the output
format in *one* place for each class -- not in every place where I might
want to print it.

You could use some stream-like object especially if you want only strings in
the format, not all the other format elements. Then have stuff like
log("error in %s: %s") <<foo << bar << flush;
or having global object
log << format("error in %s: %s") << foo << bar; // without flush last line
waits the next format()

moving the to_string() code to operator <<;
 
J

Jorgen Grahn

[It was. Thanks; that was what I suspected.]
You could use some stream-like object especially if you want only strings in
the format, not all the other format elements. Then have stuff like
log("error in %s: %s") <<foo << bar << flush;
or having global object
log << format("error in %s: %s") << foo << bar; // without flush last line
waits the next format()

Yes, I have been thinking about something like that, but most code
using the logging calls is C-like, so the benefit across the whole
code base would be fairly small => not a high priority.
moving the to_string() code to operator <<;

Actually there was no to_string() code to speak of -- like I mentioned
above it's a template which uses operator<< to fill a string stream,
and then return the resulting std::string. I have worked with code which
used T::toString() methods exclusively, and I never want to deal with
that again. operator<< is bad enough ;-)

/Jorgen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top