[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi] Local variable of rvalue reference type [Was: Micro-optimization i

From: Greg Chicares
Subject: [lmi] Local variable of rvalue reference type [Was: Micro-optimization in ledger_format]
Date: Thu, 17 Jan 2019 23:10:46 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0

On 2019-01-17 02:33, Vadim Zeitlin wrote:
> On Thu, 17 Jan 2019 01:35:30 +0000 Greg Chicares <address@hidden> wrote:
> GC> It crossed my mind to try move semantics instead, but at the time I
> GC> avoided doing so because of your review comment on PR 104. Nevertheless,
> GC> I just tried it now, with this diff vs. HEAD (which uses 'git diff -U0'
> GC> for extreme terseness):
> GC> 
> GC> diff --git a/stream_cast_test.cpp b/stream_cast_test.cpp
> GC> index d391ed6f..f7d471cd 100644
> GC> --- a/stream_cast_test.cpp
> GC> +++ b/stream_cast_test.cpp
> GC> @@ -71 +71 @@ To cast_2(From from, To = To())
> GC> -std::stringstream& imbued()
> GC> +std::stringstream imbued()
> GC> @@ -75 +75 @@ std::stringstream& imbued()
> GC> -    return interpreter;
> GC> +    return std::move(interpreter);
> GC> @@ -83 +83 @@ To cast_3(From from, To = To())
> GC> -    std::stringstream& interpreter {imbued()};
> GC> +    std::stringstream&& interpreter {imbued()};
>  I'd actually write this without "&&" in the last 2 chunks, i.e. I'd just
> use an object:
>       std::stringstream interpreter {imbued};

Please help me understand what difference this makes.

This scripture would seem to be canonical (or at least deuterocanonical
if only the Standard can be protocanonical).

| An rvalue reference is formed by placing an && after some type.
| A a;
| A&& a_ref2 = a;  // an rvalue reference

and '&&' does seem to symbolize my intention. Naively, I began with
code with single-'&' references, and I doubled the ampersands because,
I dunno, two is better than one. (And I even said yesterday that I had
measured it to be faster, although the measurements I posted actually
indicated that it was slower.)

But if I omit '&&' in the last two chunks and repeat the measurement,
the timing is the same, so is the code with '&&' omitted actually

With the omission, as you suggest:
    std::stringstream interpreter {imbued()};
clearly we're constructing a new object. I was hoping that adding '&&'
    std::stringstream&& interpreter {imbued()};
would avoid construction overhead--that, even if it calls a move ctor,
all the overhead would be optimized away, as if like this:
  std::stringstream* p_interpreter;
  std::memmove(p_interpreter, &imbued(), sizeof(std::stringstream));
But removing '&&' produced no timing difference, so clearly my hopes are
not being realized. Why not? Is a new object actually being constructed
even with '&&'? If so, why doesn't writing '&&' prevent that?

And, BTW, if my hopes were realized, then wouldn't the object that's
supposedly being moved attain a "valid but unspecified" state, such
that moving from it repeatedly in a timing loop would be unlikely to
do the right thing after the first iteration?

Furthermore, now I come across this article:
| AnyTypeMovable   v;
| AnyTypeMovable&& r = move(v);
| I'd say it's rather useless since r is now an lvalue (it has a name!)
| ...
| a named rvalue-reference is an lvalue

Is that last statement true? If so, isn't it an antinomy?

And if it's useless to declare a local variable of rvalue-reference
type, then why does N2027 declare such a variable?

reply via email to

[Prev in Thread] Current Thread [Next in Thread]