Hi Thiago,


yes, it would get more and more confusing, which variable is actually changed.

Even if the program just looks like it is changing local variables.


It is bad enough that return can have that behaviour.

It is worse that local variables get it. Or at least we should be (a bit) more explicit about it.


The value *semantics* is about mostly copying objects.

Even the return should be seen as a copy.

For performance reasons the compiler can change the copies to moves or completely elide the copies.

If we unknowingly start to modify (semi-)global objects, it is even contrary to the ideas of value semantics.


Even if bare global objects are not recommended, we effectively have them as static variables inside functions and classes, or singletons. For simplicity, I am using a global object in the next example.


struct A;

A g; // global object


A factory() {

    g.print(); // interact with the global object g

    // which is

       - already destructed, therefore UB

       - the old version, constructed with 5

       - the new version, constructed with 4

       - undefined, what it is, therefore UB

    A temp(4); // [nrvo]

    // interact with the global object g

    // interact with temp

    // they are the same now?

    return temp;



A b() {

    return factory();



int main() {

    g = A{5};

    g = b(); // we do not know, that b() calls factory()

    // factory() does not know, it is called by main()

   // nevertheless factory() modifies the target variable of the assignment within main()

    return 0;




-----Ursprüngliche Nachricht-----
Von: Thiago Macieira via Std-Proposals <std-proposals@lists.isocpp.org>
Gesendet: Do 14.09.2023 17:05
Betreff: Re: [std-proposals] Copy-construct, move-construct, and PR-construct
An: std-proposals@lists.isocpp.org;
CC: Thiago Macieira <thiago@macieira.org>;
On Tuesday, 12 September 2023 13:03:46 PDT Arthur O'Dwyer via Std-Proposals
> I'd say that such types were always meant to be supported (because why
> wouldn't they be?), and since C++17 immovable return types have been
> supported, at least in the cases that Just Work (like `return
> std::mutex();`). One certainly can't say that std::mutex wasn't "meant" to
> be returned. It's a class type; of course you can return it from a
> function! (In spirit, although not literally, each constructor of
> std::mutex *is* such a function.)

Yes, we can say that.

It was designed for and during C++11 and until C++17, it wasn't returnable.
The designers never came up with a means to do it and there doesn't seem to
have been any discussion about it.

C++17 made it possible to return this previously unreturnable type. That
doesn't mean it's a good idea. But on the other hand, returning such immovable
types appears to have been the idea of the change in C++17, so we have to
accept that.

anyway, the point isn't that we're *returning* a type. What we're doing is
create it in-place of where it shall exist once the function has returned.
That's what's happening and this is the semantic that should be discussed.
Returning is a means to an end, not the end itself. And that's what Sebastian
and I are reticent about: semantically, it makes no sense to return a mutex.

Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
  Software Architect - Intel DCAI Cloud Engineering

Std-Proposals mailing list