* 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).