public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* C++0x: rvalue references, std::vector::push_back, move semantics
@ 2010-02-03 14:12 Sebastian Mach
  0 siblings, 0 replies; 4+ messages in thread
From: Sebastian Mach @ 2010-02-03 14:12 UTC (permalink / raw)
  To: gcc-help

Hello list,

this morning I was tinkering with rvalues to get a deeper
understanding of how it works and how my own code can benefit from
them.

So I wrote up this:


  #include <iostream>
  #include <vector>
  #include <list>
  #include <utility>

  struct foo {
          foo () { std::cout << "C " << this << "\n"; }
          foo (foo const &f) { std::cout << "CC " << &f << "\n"; }
          foo (foo && f) { std::cout << "Cr " << &f << "\n"; }
          foo & operator = (foo const &f) { std::cout << "CA " << &f
<< "\n"; return *this; }
          foo & operator = (foo && f) { std::cout << "CAr " << &f <<
"\n"; return *this; }
  };
  typedef std::vector<foo> vint; // #0
  // typedef std::list<foo> vint;   // #1

where foo's copy/move-constructors print out from where they are
copied/moved, and the default printing itself's address, and vint is
just a convenience.

So far so good. Then I have

  template <typename A>
  vint operator | (A &&lhs, A &&rhs) {
          std::cout << "operator A|B{{" << std::endl;
          vint ret;
          ret.push_back(std::forward<A>(lhs));
          ret.push_back(std::forward<A>(rhs));
          std::cout << "}}" << std::endl;
          return ret;
  }

which forwards its two arguments to a newly created vint. Finally:

  int main () {
          std::cout << "----" << std::endl;
          foo() | foo();  // invoke our operator
          std::cout << "----" << std::endl;
  }


In testcase #1, with std::list<>, this will print:

----
C 0x22ff4e
C 0x22ff4f
operator A|B{{
Cr 0x22ff4f               <--- fine
Cr 0x22ff4e              <--- ditto
}}
----

As expected. But in testcase #0, with std::vector<>, I get:

----
C 0x22ff4e
C 0x22ff4f
operator A|B{{
Cr 0x22ff4f              <--- okay
Cr 0x22ff4e             <--- wonderful
Cr 0x3d2520           <--- huh?
}}
----


I understand that std::vector will default and possibly copy-construct
its entities when reserving memory:

  int main () { vint(5); }
...
  C 0x22ff5f
  CC 0x22ff5f
  CC 0x22ff5f
  CC 0x22ff5f
  CC 0x22ff5f
  CC 0x22ff5f

And I understand that vector<> might use placement new somewhere under
the hood.

But where comes 0x3d2520 from in testcase #0?


Kind regards

Sebastian Mach
phresnel@gmail.com

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: C++0x: rvalue references, std::vector::push_back, move semantics
  2010-02-04  0:11 Jonathan Wakely
@ 2010-02-04  6:50 ` Sebastian Mach
  0 siblings, 0 replies; 4+ messages in thread
From: Sebastian Mach @ 2010-02-04  6:50 UTC (permalink / raw)
  To: gcc-help

> Modify the move constructor slightly, to show 'this' as well as 'f'
> and it becomes clear:
>
>          foo (foo && f) { std::cout << "Cr " << this << ' ' << &f << "\n"; }
>
> gives
>
> ----
> C 0x7ffff943f68e
> C 0x7ffff943f68f
> operator A|B{{
> Cr 0xbaa010 0x7ffff943f68f
> Cr 0xbaa011 0x7ffff943f68e
> }}
> ----
>
> This is really nothing to do with rvalues, but rather vector's
> reallocation policy.


Hello Jonathan,

thank you for your investigation. All I can say is d'oh, especially because
I also tested list<>, and I know vector will possibly *move* data to keep it
contigous, so, d'oh.

Yes, you helped a lot in making the obvious appear to the blind.


Happy hacking
Sebastian

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: C++0x: rvalue references, std::vector::push_back, move semantics
@ 2010-02-04  0:11 Jonathan Wakely
  2010-02-04  6:50 ` Sebastian Mach
  0 siblings, 1 reply; 4+ messages in thread
From: Jonathan Wakely @ 2010-02-04  0:11 UTC (permalink / raw)
  To: Sebastian Mach; +Cc: gcc-help

re http://gcc.gnu.org/ml/gcc-help/2010-02/msg00055.html

Modify the move constructor slightly, to show 'this' as well as 'f'
and it becomes clear:

          foo (foo && f) { std::cout << "Cr " << this << ' ' << &f << "\n"; }

gives

----
C 0x7fff0df100de
C 0x7fff0df100df
operator A|B{{
Cr 0x16c0010 0x7fff0df100df
Cr 0x16c0031 0x7fff0df100de
Cr 0x16c0030 0x16c0010
}}
----

so I hope you can see that an object is move-constructed at location
0x16c0010 from lhs, then another object is move-constructed at
0x16c0031 from rhs, then the object at 0x16c0010 is moved to
0x16c0030.

The second push_back causes a reallocation, which moves ret[0]

If you add ret.reserve(2) before the calls to push_back you don't get
the reallocation:

----
C 0x7ffff943f68e
C 0x7ffff943f68f
operator A|B{{
Cr 0xbaa010 0x7ffff943f68f
Cr 0xbaa011 0x7ffff943f68e
}}
----

This is really nothing to do with rvalues, but rather vector's
reallocation policy.

Hope that helps,

Jonathan

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: C++0x: rvalue references, std::vector::push_back, move semantics
@ 2010-02-03 14:28 Sebastian Mach
  0 siblings, 0 replies; 4+ messages in thread
From: Sebastian Mach @ 2010-02-03 14:28 UTC (permalink / raw)
  To: gcc-help

Minor addendum: I post this here because I am not sure if this
a C++0x "problem", a gcc one, or none at all.


Also, of course it should be ...

template <typename A, typename B>
vint operator | (A &&lhs, A &&rhs) {
        std::cout << "operator A|B{{" << std::endl;
        vint ret;
        ret.push_back(std::forward<A>(lhs));
        ret.push_back(std::forward<B>(rhs));
        std::cout << "}}" << std::endl;
        return ret;
}

... but the results are the same.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-02-04  5:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-03 14:12 C++0x: rvalue references, std::vector::push_back, move semantics Sebastian Mach
2010-02-03 14:28 Sebastian Mach
2010-02-04  0:11 Jonathan Wakely
2010-02-04  6:50 ` Sebastian Mach

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).