Let there be two functions

std::string f(); void g(const char*); 

which i can't change. Are the following ways to use them different?

 { g(f().c_str()); } // 1 { g(f().data()); } // 2 { std::string tmp = f(); g(tmp.c_str()); } // 3 { std::string tmp = f(); g(tmp.data()); } // 4 

I would be grateful for a detailed explanation of the work of the internal kitchen in Slaves 1 and 2. A temporary variable of the type std::string , a pointer to its data is taken, passed to g() . When is this temporary variable destroyed?

Thank you answered. I will add a couple of links to EN.stackoverflow, there are references to the standard:

time

two

  • When there are questions about the moments of creation / destruction, the easiest way to test this in practice is a custom class with text output in constructors / destructors. - αλεχολυτ
  • @alexolut I, of course, did it before asking a question. Unfortunately, this does not solve the problem of compiler-dependent behavior. - andy.37
  • in this case, it should not depend on the compiler. And in dependent cases, you are more likely to check on the same compiler, where you use the final code. Unless of course do not develop the library supplied in source code. In the latter case, of course, you must rely on the letter of the Standard. But even here a situation is possible when the compiler has a known implementation error that requires a workaround. - αλεχολυτ
  • The ability to use data() instead of c_str() only available starting from C ++ 11. Until C ++ 11, it was not guaranteed that data() would return a C-string. - AnT
  • @AnT, once unsubscribed, do I understand correctly that in C ++ 11 data and c_str are full equivalents? - andy.37

2 answers 2

Ways differ only in a spelling, they do not differ in behavior. Temporary variables are always destroyed upon completion of the execution of the full expression . Relevant paragraphs in C ++ 14: [intro.execution] p10 and [class.temporary] p3

  • Thank you, this is closer to what I wanted to hear. Clarification, in the context of (1) is a full expression a whole g(f().c_str()) or part of f().c_str() too? What will happen if we write char *p = f().c_str(); ? - andy.37
  • @ andy.37, f().c_str() is a subexpression of the first. Full expressions, very roughly, are expressions ending ; . 1st and 3rd are full expressions. - ixSci
  • @ andy.37 Right here - const char * p = f().c_str(); g(p); const char * p = f().c_str(); g(p); you really are in trouble. Because the string returned by f() will be destroyed before calling g() . - Harry
  • @Harry I thought so. OK, thank you all, we will assume that the answer is received)) - andy.37

In the last two cases, at the end of g() , you will have a tmp variable that you can continue to work with. In the first two cases, access to the string returned by f() will not be, it will be destroyed at the end of g() automatically.

In any case, while the function is running, its arguments remain in scope, so that until the function completes, the destruction of the argument will not occur.

  • It is clear. For simplicity, corrected the question. It is the behavior of g that interests - whether it is always the same - andy.37
  • it will be destroyed at the end of the work g () automatically (s). Clarification - is it true at the end of g ? - andy.37
  • Then essentially nothing. Unless theoretically, as far as I remember, once the data() call did not guarantee the presence of a terminating null character. Starting with C ++ 11, they are identical. - Harry
  • @ andy.37 The counter question - when? The point of following, as I understand it, upon the completion of g() , the scope is — bye-bye ... Do you think the compiler will postpone the destruction until exiting the block? :) - Harry
  • Rather, I fear the opposite - the pointer is created, the pointer is calculated, and destroyed before the call to g () , making the pointer invalid. - andy.37