Are the addresses of two temporaries guaranteed to be different in the same expression?

Two alive objects in C++ (almost) always have different addresses.

Since temporaries in #1 #2 have non-overlapping lifetimes, the compiler is free to reuse the storage of #1 for #2 .

But in #3 all temporaries are alive until the end of the expression (for obvious reasons) and in this case they have to have different addresses.

C++ does not support guaranteed caching of the same sub-expressions apart from the "as if" rule. Meaning that if you do not take the address, it is perfectly reasonable for the compiler to store them however it likes or not store them at all.

Reference

N4861 Draft C++20 [6.7.9.2] Unless an object is a bit-field or a subobject of zero size, the address of that object is the address of the first byte it occupies. Two objects with overlapping lifetimes that are not bit-fields may have the same address if one is nested within the other, or if at least one is a subobject of zero size and they are of different types;otherwise, they have distinct addresses and occupy disjoint bytes of storage. ^28

In your case, the exceptions do not apply. The footnote ^28 also says exactly what I have written above:

^28: Under the “as-if” rule an implementation is allowed to store two objects at the same machine address or not store an object at all if the program cannot observe the difference.

Edit

Excellent question from @RiaD:

But do these two 42s have to be different objects? For example, "abc" and "abc" can be the same array.

The behaviour depends on the kind of the literal used and is precisely defined in N4861 Draft C++20 5.13 [lex.literal].

  1. String literals are an exception among all literal kinds because they are classified as lvalues and thus have an address.

    [lex.string.14] Evaluating a string-literal results in a string literal object with static storage duration, initialized from the given characters as specified above. Whether all string-literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a different object is unspecified.

    Meaning the literals might have the same address as @RiaD observed but that is not in contradiction with the above because they are the same object.

  2. All other literals, including integers, are prvalue expressions which are not objects (in a sense that they do not have an address), but in certain cases they spawn a temporary object through temporary materialization which happens for foo(42) because it is bound to a const T&. AFAIK the Standard does not explicitly say that same two prvalue expressions have to spawn a different temporary, but it says that an expression initializes a temporary, so I believe each expression has to create a new temporary, the lifetimes are also slightly different. So, two addresses (if observed) must be different.


Temporaries persist until the end of the full expression that caused them to spring to life.

[class.temporary]

4 ... Temporary objects are destroyed as the last step in evaluating the full-expression ([intro.execution]) that (lexically) contains the point where they were created.

This is true of all temporaries. This means that in expression #3, assuming its evaluation ends without throwing an exception, both temporaries could have overlapping lifetimes.

With few exceptions (none of which apply here), two different objects within their lifetime will have different addresses.