1

OK I have this sequence of events:

  1. I construct an r-value object
  2. I pass an iterator to that r-value object into a function as a parameter
  3. The function operates on this iterator
  4. The function returns this iterator by value
  5. I dereference the iterator

I don't know what causes cleanup of the r-value object, is it the termination of that line?

OK, now for specifics, I'm trying to come up with a better answer for this question: string Multiplication in C++ And I have the code:

const auto bar = 13U;
const char multiplicand[] = "0, ";
const auto length = strlen(multiplicand);
const string foo(&*generate_n(string(bar * length, '\0').begin(), bar * length, [&]() {
    static auto i = 0U;
    return multiplicand[i++ % length];
}) - bar * length);

So I want to know when the string that's constructed inside generate_n should be destroyed. Incidentally this seems to work fine on gcc 5.1: http://ideone.com/Y8rDs5 But I could just be getting undefined behavior. This is implied by the fact that the code segfaults on Visual Studio 2015.

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 1
    Doesn't [this](http://stackoverflow.com/questions/2506793/c-life-span-of-temporary-arguments) answer this about the lifetime? – NathanOliver Feb 23 '16 at 14:34
  • @NathanOliver It does, say: "Usually this means it ends at the `;` (or `)`, `for`, `if`, `while`, `switch` etc.) denoting the end of the statement. In your example, it's the end of the function call." I think that the `)` is the answer to my question. But the "Usually" in that statement is not definitive. If the cleanup should be delayed until the `;` then I'm golden, but that would mean that Microsoft is doing it wrong... – Jonathan Mee Feb 23 '16 at 14:43
  • 1
    I don't know if this code invokes UB, but a better answer to anything it is not. – n. m. could be an AI Feb 23 '16 at 15:16
  • @n.m. Lol, perhaps: http://stackoverflow.com/q/35506712/2642059 could benefit from some of your wisdom? I'd be pretty excited if I could do string multiplication to initialize a `const string`, honestly I'd be excited about it even if it was ugly. – Jonathan Mee Feb 23 '16 at 15:20
  • 1
    Return `std::string` from a function by value. The compiler knows how to optimize it. – n. m. could be an AI Feb 23 '16 at 15:30

1 Answers1

1

Temporaries such as string(bar * length, '\0') are destroyed at the end of the full expression. The full expression is the initializer of const string foo. Hence, the temporary string will not be destroyed before the ctor of foo returns.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • That's what I thought as well from reading section 12.2. However, our opinions aren't enough to support this answer. Can you give a source? – Jonathan Mee Feb 24 '16 at 11:28
  • The source is indeed 12.2. Note that the apparent exception does not apply: " There are two contexts in which temporaries are destroyed at a different point than the end of the full expression. The first context is when **an expression appears as an initializer** for a declarator defining an object. In that context, the temporary that holds the result of the expression shall persist until the object’s initialization is complete". This doesn't apply because it applies only to the temporary from the full expression, not to any other temporaries. – MSalters Feb 24 '16 at 11:37
  • OK, I agree, but that's the temporary that holds the *return*. 12.2[class.temporary]2 says of the expression `X b = f(X(2));`: "An implementation might use a temporary in which to construct `X(2)` before passing it to `f()` using `X`’s copy constructor; alternatively, `X(2)` might be constructed in the space used to hold the argument." My problem is, if the argument is not pass by value, when is the temporary/space used to hold the argument cleaned up? – Jonathan Mee Feb 24 '16 at 11:47
  • 6.6.3[stmt.return]3"The copy-initialization of the returned entity is sequenced before the destruction of temporaries at the end of the full-expression established by the operand of the return statement, which, in turn, is sequenced before the destruction of local variables (6.6) of the block enclosing the return statement." This seems to indicate that upon `return` a "full-expression" is complete, though it's unclear if temporaries constructed as arguments are considered "local variables" – Jonathan Mee Feb 24 '16 at 12:49