C++0x: rvalue references, std::vector::push_back, move semantics

Sebastian Mach phresnel@googlemail.com
Wed Feb 3 14:12:00 GMT 2010


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



More information about the Gcc-help mailing list