Why do un-named C++ objects destruct before the scope block ends?
A temporary variable lives until the end of the full expression it was created in. Yours ends at the semicolon.
This is in 12.2/3:
Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created.
Your behavior is guaranteed.
There are two conditions that, if met, will extend the lifetime of a temporary. The first is when it's an initializer for an object. The second is when a reference binds to a temporary.
The rules that govern the lifetimes of temporary objects have nothing to do with notion of scope. Scope is a property of a name, and temporary objects do not have names. In other words, temporary objects have no scope.
Most of the time the lifetime of a temporary object ends at the end of the full expression that created that object, which is what you observed in your experiment. This is the general rule that has some exceptions. The main one is that if you immediately attach a reference to your temporary object, the lifetime of the object will be extended to match the lifetime of the reference
const Foo &rfoo = Foo("one");
The above temporary will live as long as rfoo
lives.