Topic: On destructive move
Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Mon, 11 Aug 2014 22:57:16 -0400
Raw View
On Aug 11, 2014, at 6:45 PM, Zhihao Yuan <zy@miator.net> wrote:
> Whatever... We have two papers proposing destructive move, and I
> just want to share some... sympathy.
What I have to say is not a proposal. I merely want to shine some light on=
the topic of destructive move.
Early in 2001, when I first began investigating move semantics, I realized =
that there were four fundamental move operations. One can think of them in=
terms of target and source, and constructed and destructed.
In all cases, a source is moved to a target.
In all cases, the source is in a constructed state prior to the move, and t=
he target is in a constructed state after the move.
If you accept the syntax:
before after
-----------/-----------
constructed/constructed
constructed/destructed
destructed /constructed
destructed /destructed
to refer to the state of the source and target, before and after the move, =
then this all comes down to the following 4 possibilities:
target source
before after before after
-----------/----------- -----------/-----------
move assignment constructed/constructed constructed/constructed
constructed/constructed constructed/destructed
move construction destructed /constructed constructed/constrcuted
destructed /constructed constructed/destructed
The first and third rows represent what we today know as move assignment an=
d move construction, respectively.
The second and forth rows represent an assignment operator, and a construct=
or, where the source is destructed after the operation.
It turns out that our ever-useful vector makes use of all 4 of these move o=
perations.
1. A move assignment operation is ideal for moving v[0] to v[1] during an =
insert operation, where the vector has sufficient capacity and initially ha=
s length greater than 1. The same move assignment is just as useful during=
an erase.
2. A move construction is very useful when moving v.back() to v[v.size()] =
during an insert with sufficient capacity.
3. The 2nd row (call it a destructive move constructor) is useful during a=
vector realloc when moving v[i] from the old buffer to the new buffer. We=
currently simulate this with a move construction followed by a destruction=
on the source.
4. The 4th row (call it a destructive move assignment) is useful when movi=
ng v.back() to v[v.size()-2] during an erase.
The reason N1377 did not propose the 2nd and 4th rows above was two-fold:
1. I didn't know how to solve all the problems associated with these two r=
ows.
2. Even if I had figured it out, the resulting proposal would have been to=
o complicated to get through committee, and we would not have the opportuni=
ty to have this conversation today.
I believe rows 2 and 4 have value. They don't have as much value as rows 1=
and 3 because they can be emulated by rows 1 and 3 followed by a call to t=
he destructor. But still they have value. It is my hope that if we are to=
entertain destructive move semantics that both rows 2 and 4 will be consid=
ered, as opposed to only one or the other.
I encourage proposers to address the concerns written about at:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Alternati=
ve%20move%20designs
under the title "Destructive move semantics", especially the interim state =
of an object composed of other objects, while moving, while respecting the =
"correct" order of construction and destruction of the sub-objects.
Howard
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: David Krauss <potswa@gmail.com>
Date: Tue, 12 Aug 2014 11:21:42 +0800
Raw View
--Apple-Mail=_53A76462-EC9F-48BC-90D2-B0D026AD4417
Content-Type: text/plain; charset=ISO-8859-1
On 2014-08-12, at 10:57 AM, Howard Hinnant <howard.hinnant@gmail.com> wrote:
> I encourage proposers to address the concerns written about at:
I see solutions presented there, but not problems.
What added value could make up for the cost of unbinding destruction from scoping?
Is there any efficiency gain that can't reasonably be reaped by an optimizer?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--Apple-Mail=_53A76462-EC9F-48BC-90D2-B0D026AD4417
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space;"><br><div><div>On 2014&=
ndash;08–12, at 10:57 AM, Howard Hinnant <<a href=3D"mailto:howard=
..hinnant@gmail.com">howard.hinnant@gmail.com</a>> wrote:</div><br class=
=3D"Apple-interchange-newline"><blockquote type=3D"cite"><span style=3D"fon=
t-family: Helvetica; font-size: 12px; font-style: normal; font-variant: nor=
mal; font-weight: normal; letter-spacing: normal; line-height: normal; orph=
ans: auto; text-align: start; text-indent: 0px; text-transform: none; white=
-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width:=
0px; float: none; display: inline !important;">I encourage proposers to ad=
dress the concerns written about at:</span><br style=3D"font-family: Helvet=
ica; font-size: 12px; font-style: normal; font-variant: normal; font-weight=
: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-=
align: start; text-indent: 0px; text-transform: none; white-space: normal; =
widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"></blockqu=
ote></div><br><div>I see solutions presented there, but not problems.</div>=
<div><br></div><div>What added value could make up for the cost of unbindin=
g destruction from scoping?</div><div><br></div><div>Is there any efficienc=
y gain that can’t reasonably be reaped by an optimizer?</div><div><br=
></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_53A76462-EC9F-48BC-90D2-B0D026AD4417--
.
Author: Marc <marc.glisse@gmail.com>
Date: Tue, 12 Aug 2014 07:54:20 -0700 (PDT)
Raw View
------=_Part_4142_1353686000.1407855260409
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Le mardi 12 ao=C3=BBt 2014 04:57:21 UTC+2, Howard Hinnant a =C3=A9crit :
>
> this all comes down to the following 4 possibilities:=20
>
> target source=20
> before after before after=20
> -----------/----------- -----------/-----------=
=20
> move assignment constructed/constructed constructed/constructed=
=20
> constructed/constructed constructed/destructed=
=20
> move construction destructed /constructed constructed/constructed=
=20
> destructed /constructed constructed/destructed=
=20
>
> The first and third rows represent what we today know as move assignment=
=20
> and move construction, respectively.=20
>
> The second and forth rows represent an assignment operator, and a=20
> constructor, where the source is destructed after the operation.=20
>
> It turns out that our ever-useful vector makes use of all 4 of these move=
=20
> operations.=20
>
> 1. A move assignment operation is ideal for moving v[0] to v[1] during a=
n=20
> insert operation, where the vector has sufficient capacity and initially=
=20
> has length greater than 1. The same move assignment is just as useful=20
> during an erase.=20
>
> 2. A move construction is very useful when moving v.back() to v[v.size()=
]=20
> during an insert with sufficient capacity.=20
>
=20
For both 1 and 2, it isn't obvious to me why you want to keep the source in=
=20
a constructed state. Assuming the insertion is done with emplace(), you=20
will need to call a constructor for the new element anyway, so you want the=
=20
space where this will happen destructed.
3. The 2nd row (call it a destructive move constructor) is useful during a=
=20
> vector realloc when moving v[i] from the old buffer to the new buffer. W=
e=20
> currently simulate this with a move construction followed by a destructio=
n=20
> on the source.=20
>
> 4. The 4th row (call it a destructive move assignment) is useful when=20
> moving v.back() to v[v.size()-2] during an erase.=20
>
I think you swapped the explanations for rows 2 and 4, but it is easy=20
enough to reconnect.
The reason N1377 did not propose the 2nd and 4th rows above was two-fold:=
=20
>
> 1. I didn=E2=80=99t know how to solve all the problems associated with t=
hese two=20
> rows.=20
> 2. Even if I had figured it out, the resulting proposal would have been=
=20
> too complicated to get through committee, and we would not have the=20
> opportunity to have this conversation today.=20
>
> I believe rows 2 and 4 have value. They don=E2=80=99t have as much value=
as rows=20
> 1 and 3 because they can be emulated by rows 1 and 3 followed by a call t=
o=20
> the destructor. But still they have value. It is my hope that if we are=
=20
> to entertain destructive move semantics that both rows 2 and 4 will be=20
> considered, as opposed to only one or the other.=20
>
The emulation argument is a bit strange: row 1 can be implemented as a=20
swap, and row 3 can be emulated by row 4 followed by a call to the default=
=20
constructor, and that's very often what their implementations look like in=
=20
practice (which makes emulating 4 with 3 look like=20
4+constructor+destructor...). But 4 has the added particularity that it=20
only has 1 object constructed at a time, while emulating it requires having=
=20
2 live objects at some point, which is bad for noexcept (and for=20
performance). I would argue that 4 is the most important one for=20
performance, we mostly ended up with 1 and 3 because they were safer. And I=
=20
don't mind getting 2 for completeness.
(just arguing details, I agree that it isn't an easy problem)
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_4142_1353686000.1407855260409
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Le mardi 12 ao=C3=BBt 2014 04:57:21 UTC+2, Howard Hinnant =
a =C3=A9crit :<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"> this all c=
omes down to the following 4 possibilities:
<br>
<br> &=
nbsp; target =
source
<br> &=
nbsp; before after =
before after
<br> --=
---------/----------- -----------/-----------
<br>move assignment constructed/constructed &nbs=
p; constructed/constructed
<br> co=
nstructed/constructed constructed/destructed
<br>move construction destructed /constructed co=
nstructed/constructed
<br> de=
structed /constructed constructed/destructed
<br>
<br>The first and third rows represent what we today know as move assignmen=
t and move construction, respectively.
<br>
<br>The second and forth rows represent an assignment operator, and a const=
ructor, where the source is destructed after the operation.
<br>
<br>It turns out that our ever-useful vector makes use of all 4 of these mo=
ve operations.
<br>
<br>1. A move assignment operation is ideal for moving v[0] to v[1] d=
uring an insert operation, where the vector has sufficient capacity and ini=
tially has length greater than 1. The same move assignment is just as=
useful during an erase.
<br>
<br>2. A move construction is very useful when moving v.back() to v[v=
..size()] during an insert with sufficient capacity.
<br></blockquote><div> <br>For both 1 and 2, it isn't obvious to me wh=
y you want to keep the source in a constructed state. Assuming the insertio=
n is done with emplace(), you will need to call a constructor for the new e=
lement anyway, so you want the space where this will happen destructed.<br>=
<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">3. The 2nd row=
(call it a destructive move constructor) is useful during a vector realloc=
when moving v[i] from the old buffer to the new buffer. We currently=
simulate this with a move construction followed by a destruction on the so=
urce.
<br>
<br>4. The 4th row (call it a destructive move assignment) is useful =
when moving v.back() to v[v.size()-2] during an erase.
<br></blockquote><div><br>I think you swapped the explanations for rows 2 a=
nd 4, but it is easy enough to reconnect.<br><br></div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;">The reason N1377 did not propose the 2nd and 4th r=
ows above was two-fold:
<br>
<br>1. I didn=E2=80=99t know how to solve all the problems associated=
with these two rows.
<br>2. Even if I had figured it out, the resulting proposal would hav=
e been too complicated to get through committee, and we would not have the =
opportunity to have this conversation today.
<br>
<br>I believe rows 2 and 4 have value. They don=E2=80=99t have as muc=
h value as rows 1 and 3 because they can be emulated by rows 1 and 3 follow=
ed by a call to the destructor. But still they have value. It i=
s my hope that if we are to entertain destructive move semantics that both =
rows 2 and 4 will be considered, as opposed to only one or the other.
<br></blockquote><div><br>The emulation argument is a bit strange: row 1 ca=
n be implemented as a swap, and row 3 can be emulated by row 4 followed by =
a call to the default constructor, and that's very often what their impleme=
ntations look like in practice (which makes emulating 4 with 3 look like 4+=
constructor+destructor...). But 4 has the added particularity that it only =
has 1 object constructed at a time, while emulating it requires having 2 li=
ve objects at some point, which is bad for noexcept (and for performance). =
I would argue that 4 is the most important one for performance, we mostly e=
nded up with 1 and 3 because they were safer. And I don't mind getting 2 fo=
r completeness.<br><br>(just arguing details, I agree that it isn't an easy=
problem)<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4142_1353686000.1407855260409--
.
Author: Zhihao Yuan <zy@miator.net>
Date: Tue, 12 Aug 2014 14:01:41 -0400
Raw View
--20cf3030c11fbafc0405007276f5
Content-Type: text/plain; charset=UTF-8
On Mon, Aug 11, 2014 at 10:57 PM, Howard Hinnant <howard.hinnant@gmail.com>
wrote:
>
> The reason N1377 did not propose the 2nd and 4th rows above was two-fold:
>
> 1. I didn't know how to solve all the problems associated with these two
> rows.
> 2. Even if I had figured it out, the resulting proposal would have been
> too complicated to get through committee, and we would not have the
> opportunity to have this conversation today.
>
I agree.
What I can imagine is to have two mechanisms of destructive move,
one for objects on stack, similar to the restrictions of ARB, so that we
can track the lifetime; another for heap allocation and subobjects, with
the aligned storage trick. The later one is already being used in some
libraries, and the first one wraps the later for end user to use.
But it's still too complex, at least not as simple as destructive move
the concept itself.
In contrast, C++11 move is one mechanism which works everywhere,
as simple as copying.
--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://bit.ly/blog4bsd
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--20cf3030c11fbafc0405007276f5
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Mon, Aug 11, 2014 at 10:57 PM, Howard Hinnant <span dir=
=3D"ltr"><<a href=3D"mailto:howard.hinnant@gmail.com" target=3D"_blank">=
howard.hinnant@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra=
"><div class=3D"gmail_quote">
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><br>
The reason N1377 did not propose the 2nd and 4th rows above was two-fold:<b=
r>
<br>
1. =C2=A0I didn't know how to solve all the problems associated with th=
ese two rows.<br>
2. =C2=A0Even if I had figured it out, the resulting proposal would have be=
en too complicated to get through committee, and we would not have the oppo=
rtunity to have this conversation today.<br></blockquote><div><br></div><di=
v>
I agree.<br><br>What I can imagine is to have two mechanisms of destructive=
move,<br>one for objects on stack, similar to the restrictions of ARB, so =
that we<br>can track the lifetime; another for heap allocation and subobjec=
ts, with<br>
the aligned storage trick.=C2=A0 The later one is already being used in som=
e<br>libraries, and the first one wraps the later for end user to use.<br><=
br></div><div>But it's still too complex, at least not as simple as des=
tructive move<br>
the concept itself.<br><br></div><div>In contrast, C++11 move is one mechan=
ism which works everywhere,<br></div><div>as simple as copying.<br></div></=
div></div><div class=3D"gmail_extra"><br>-- <br>Zhihao Yuan, ID lichray<br>
The best way to predict the future is to invent it.<br>____________________=
_______________________________<br>4BSD -- <a href=3D"http://bit.ly/blog4bs=
d" target=3D"_blank">http://bit.ly/blog4bsd</a>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--20cf3030c11fbafc0405007276f5--
.