0

I've been questioning myself whether Temporary Objects do have identity. I know that the following is valid:

object.temporary_object().modify()

as far as the object returned is non-const or the function called on the object do not modify immutable members.

According to the value categories definition, prvalues results can be moved but have no identity and as Temporary Objects are result of prvalue expressions, how can they be modified?

Nazinho
  • 311
  • 2
  • 8
  • *maybe* related, to understand identity better: https://stackoverflow.com/questions/50783525/what-does-it-mean-xvalue-has-identity – geza Sep 13 '18 at 17:08
  • @geza Thanks, that answer helped me understanding better the relation xvalue-identity – Nazinho Sep 13 '18 at 18:31
  • @downvoters can you explain the -1? This question seems perfectly reasonable to me. – Nazinho Sep 13 '18 at 18:32

2 Answers2

5

The linked document is not normative. In some sense it seems to describe what prvalues ought to be, rather than what they were at the time. In C++17, it became true that prvalues have no identity---but in C++11 and C++14, it was not quite so.

In C++11 and C++14, a prvalue of class type does have an identity, because, as you've observed, it's possible to call a method on it, and there are also ways to observe its address. Similarly, prvalues of array type have identity. Prvalues of scalar type (e.g., integer literals) do not have identity. Binding them to references will cause the materialization of a temporary object, which now has an address but is no longer observable as a prvalue.

In C++17, prvalues have no identity, and are not temporary objects, but are instead expressions that can be used to create temporary (or non-temporary) objects. Moving from a prvalue to an object effectively "invokes" the prvalue. A temporary object is only observable as an xvalue.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • 1
    Tangentally and amusingly to me, you can create a C++ type that behaves somewhat like a prvalue expression does, but can itself be treated as an object separate from what it creates: `templatestruct prvalue{ F f; operator std::invoke_result_t()&&{ return f(); } };` – Yakk - Adam Nevraumont Sep 13 '18 at 18:28
1

You can modify the temporary object just like any other. The modifications will just be moot as they are thrown away when the life-time of the temporary object ends and it is destructed.

It's kind of similar to something like this:

SomeClass object;
// Some code...

{
    // Entering a new scope, the life-time of variables in here ends when the scope ends
    SomeOtherClass temporary_object = object.temporary_object();

    temporary_object.modify();

    // Now the scope ends, and the life-time of temporary_object with it
}

// Here there exists no such things as "temporary_object"

All modifications you made to temporary_objects will be lost when the nested scope ends, and temporary_object is destructed.


One important disclaimer: You can design the SomeOtherClass (from the above example) to keep a link (reference or pointer) to object, and the modify() function can use that link to modify object itself. Those modifications will still exist after temporary_object is destructed, as they are modification on object itself instead of temporary_object.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621