<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/2.2.2" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
	<title>Comments on: Rvalue reference pitfalls</title>
	<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/</link>
	<description>Boris Kolpackov's blog about software</description>
	<pubDate>Thu, 09 Apr 2026 12:08:19 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2.2</generator>

	<item>
		<title>By: haohaolee</title>
		<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1906</link>
		<author>haohaolee</author>
		<pubDate>Mon, 12 Mar 2012 09:46:48 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1906</guid>
		<description>FYI, this article discussed the similar problem
http://cpptruths.blogspot.com/2012/03/rvalue-references-in-constructor-when.html</description>
		<content:encoded><![CDATA[<p>FYI, this article discussed the similar problem<br />
<a href="http://cpptruths.blogspot.com/2012/03/rvalue-references-in-constructor-when.html" rel="nofollow">http://cpptruths.blogspot.com/2012/03/rvalue-references-in-constructor-when.html</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Johannes</title>
		<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1897</link>
		<author>Johannes</author>
		<pubDate>Tue, 06 Mar 2012 20:50:03 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1897</guid>
		<description>This article confuses the type of a variable "x" with the type of an expression that refers to it ("x"). The type of the variable in your example is and stays "int&#38;&#38;". The expression that refers to it has type "int" . That type is neither an rvalue reference nor lvalue reference. But what is important is that that expression is an lvalue. Instead of an xvalue. An expression has never a reference type in C++.</description>
		<content:encoded><![CDATA[<p>This article confuses the type of a variable &#8220;x&#8221; with the type of an expression that refers to it (&#8221;x&#8221;). The type of the variable in your example is and stays &#8220;int&amp;&amp;&#8221;. The expression that refers to it has type &#8220;int&#8221; . That type is neither an rvalue reference nor lvalue reference. But what is important is that that expression is an lvalue. Instead of an xvalue. An expression has never a reference type in C++.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Boris Kolpackov</title>
		<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1896</link>
		<author>Boris Kolpackov</author>
		<pubDate>Tue, 06 Mar 2012 20:22:46 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1896</guid>
		<description>Jonathan, very interesting idea. I believe this will work, provided the argument type supports move construction. The cost is just an extra move constructor call, which should be cheap (or even inlined away).</description>
		<content:encoded><![CDATA[<p>Jonathan, very interesting idea. I believe this will work, provided the argument type supports move construction. The cost is just an extra move constructor call, which should be cheap (or even inlined away).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jonathan Rogers</title>
		<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1895</link>
		<author>Jonathan Rogers</author>
		<pubDate>Tue, 06 Mar 2012 19:51:23 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1895</guid>
		<description>One thing I would like to point out is that your use of two constructors, one taking a const std::shared_ptr&#38; and the other taking an std::shared_ptr&#38;&#38; might not be the best approach.

Because of the fact that you you have the &#38;&#38; version, it implies that you are planning on storing the shared ptr in your object.

The correct thing to do in this case is to have just one constructor, a constructor that takes the shared_ptr by value. You then treat the by value argument as you do in the in the shared_ptr&#38;&#38; version, using std::move to take the pointer.

This will handle all cases efficiently while only requiring one constructor.

In general, if you find yourself writing two versions of a function, one taking an Rvalue reference, you can probably use this optimisation. (Except for the actual move constructor of an object)</description>
		<content:encoded><![CDATA[<p>One thing I would like to point out is that your use of two constructors, one taking a const std::shared_ptr&amp; and the other taking an std::shared_ptr&amp;&amp; might not be the best approach.</p>
<p>Because of the fact that you you have the &amp;&amp; version, it implies that you are planning on storing the shared ptr in your object.</p>
<p>The correct thing to do in this case is to have just one constructor, a constructor that takes the shared_ptr by value. You then treat the by value argument as you do in the in the shared_ptr&amp;&amp; version, using std::move to take the pointer.</p>
<p>This will handle all cases efficiently while only requiring one constructor.</p>
<p>In general, if you find yourself writing two versions of a function, one taking an Rvalue reference, you can probably use this optimisation. (Except for the actual move constructor of an object)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Boris Kolpackov</title>
		<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1894</link>
		<author>Boris Kolpackov</author>
		<pubDate>Tue, 06 Mar 2012 17:59:22 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1894</guid>
		<description>Thomas, no I haven't missed the part about perfect forwarding and I realize that the same mechanism that caused problems in my case is what allows perfect forwarding in the first place. I should have probably mentioned that, but now you have corrected my omission, thanks ;-).

Your suggestion about the constructor signatures, however, won't works. There are several problems with. Firstly, this set of constructors won't allow initialization with a const reference to id:

const string id ("abc");
lazy_shared_ptr&#60;object&gt; lp (db, id);

Then, there is the same problem when initializing with a non-const lvalue reference to shared_ptr. Instead of the second constructor, the first constructor will be called:

shared_ptr&#60;object&gt; p (...);
lazy_shared_ptr&#60;object&gt; lp (db, p);</description>
		<content:encoded><![CDATA[<p>Thomas, no I haven&#8217;t missed the part about perfect forwarding and I realize that the same mechanism that caused problems in my case is what allows perfect forwarding in the first place. I should have probably mentioned that, but now you have corrected my omission, thanks ;-).</p>
<p>Your suggestion about the constructor signatures, however, won&#8217;t works. There are several problems with. Firstly, this set of constructors won&#8217;t allow initialization with a const reference to id:</p>
<p>const string id (&#8221;abc&#8221;);<br />
lazy_shared_ptr&lt;object> lp (db, id);</p>
<p>Then, there is the same problem when initializing with a non-const lvalue reference to shared_ptr. Instead of the second constructor, the first constructor will be called:</p>
<p>shared_ptr&lt;object> p (&#8230;);<br />
lazy_shared_ptr&lt;object> lp (db, p);</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Boris Kolpackov</title>
		<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1893</link>
		<author>Boris Kolpackov</author>
		<pubDate>Tue, 06 Mar 2012 17:49:45 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1893</guid>
		<description>Benjamin, the base constructor will only move the 'base' part of the object. The nums members, which is in the 'derived' part, will be unaffected (base doesn't know anything about it).</description>
		<content:encoded><![CDATA[<p>Benjamin, the base constructor will only move the &#8216;base&#8217; part of the object. The nums members, which is in the &#8216;derived&#8217; part, will be unaffected (base doesn&#8217;t know anything about it).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Benjamin Schindler</title>
		<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1892</link>
		<author>Benjamin Schindler</author>
		<pubDate>Tue, 06 Mar 2012 16:25:55 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1892</guid>
		<description>Humm... the reason why a named r-value reference is an l-value because it can be used multiple times. So, in your example: 

object (object&#38;&#38; obj)
      : base (std::move (obj)),
        nums (std::move (obj.nums))
  {
  }

you use obj 2 times. Since the base constructor is called first, obj.nums can be set to an invalid value. Why? If the base constructor constructs an object using a move constructor, obj.nums could be invalidated leading to (I think) undefined behavior.. 
Am I completely off on this?</description>
		<content:encoded><![CDATA[<p>Humm&#8230; the reason why a named r-value reference is an l-value because it can be used multiple times. So, in your example: </p>
<p>object (object&amp;&amp; obj)<br />
      : base (std::move (obj)),<br />
        nums (std::move (obj.nums))<br />
  {<br />
  }</p>
<p>you use obj 2 times. Since the base constructor is called first, obj.nums can be set to an invalid value. Why? If the base constructor constructs an object using a move constructor, obj.nums could be invalidated leading to (I think) undefined behavior..<br />
Am I completely off on this?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Thomas</title>
		<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1891</link>
		<author>Thomas</author>
		<pubDate>Tue, 06 Mar 2012 16:02:38 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1891</guid>
		<description>Sorry, it should be :
inner(std::forward "Angle brackets" T "Angle brackets"(t);</description>
		<content:encoded><![CDATA[<p>Sorry, it should be :<br />
inner(std::forward &#8220;Angle brackets&#8221; T &#8220;Angle brackets&#8221;(t);</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Thomas</title>
		<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1890</link>
		<author>Thomas</author>
		<pubDate>Tue, 06 Mar 2012 15:35:55 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1890</guid>
		<description>"There doesn’t seem to be a way to provide such a move constructor. The more general conclusion seems to be this: function templates with arguments of rvalue references that are formed directly from template arguments can be transformed, with unpredictable results, to functions that have lvalue references instead.

Hello. You seem to have miss the part about perfect forwarding when studying rvalue reference. The deduction rules are different when using rvalue reference and template. They are designed to allowed perfect forwading. Try this :

void inner(const int&#38; i)
{
   std::cout 
void outer(T&#38;&#38; t)
{
  inner(std::forward(t);
}

int i;
outer(i); // will go to inner(const int&#38;)
outer(5); // will go to inner(int&#38;&#38;)

So in your case, you need only 3 constructors to lazy_shared_ptr. It should look like this :

 // template case, perfect forward lvalue or rvalue all in one
 template 
 lazy_shared_ptr (database&#38; d, ID&#38;&#38; id)
{
   d.init(std::forward(id));
}
 
// non template case, constructor for lvalue
 template 
 lazy_shared_ptr (database&#38; d, const std::shared_ptr&#38; t)
{
  d.init(t);
}
 
// non template case, constructor for rvalue
template 
lazy_shared_ptr (database&#38; d, std::shared_ptr&#38;&#38; t);
{
   d.init(std::move(t));
}</description>
		<content:encoded><![CDATA[<p>&#8220;There doesn’t seem to be a way to provide such a move constructor. The more general conclusion seems to be this: function templates with arguments of rvalue references that are formed directly from template arguments can be transformed, with unpredictable results, to functions that have lvalue references instead.</p>
<p>Hello. You seem to have miss the part about perfect forwarding when studying rvalue reference. The deduction rules are different when using rvalue reference and template. They are designed to allowed perfect forwading. Try this :</p>
<p>void inner(const int&amp; i)<br />
{<br />
   std::cout<br />
void outer(T&amp;&amp; t)<br />
{<br />
  inner(std::forward(t);<br />
}</p>
<p>int i;<br />
outer(i); // will go to inner(const int&amp;)<br />
outer(5); // will go to inner(int&amp;&amp;)</p>
<p>So in your case, you need only 3 constructors to lazy_shared_ptr. It should look like this :</p>
<p> // template case, perfect forward lvalue or rvalue all in one<br />
 template<br />
 lazy_shared_ptr (database&amp; d, ID&amp;&amp; id)<br />
{<br />
   d.init(std::forward(id));<br />
}</p>
<p>// non template case, constructor for lvalue<br />
 template<br />
 lazy_shared_ptr (database&amp; d, const std::shared_ptr&amp; t)<br />
{<br />
  d.init(t);<br />
}</p>
<p>// non template case, constructor for rvalue<br />
template<br />
lazy_shared_ptr (database&amp; d, std::shared_ptr&amp;&amp; t);<br />
{<br />
   d.init(std::move(t));<br />
}</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Boris Kolpackov</title>
		<link>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1889</link>
		<author>Boris Kolpackov</author>
		<pubDate>Tue, 06 Mar 2012 15:09:29 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/03/06/rvalue-reference-pitfalls/#comment-1889</guid>
		<description>At the moment I still think rvalue references are a good thing. They are complex, yes, but I don't think this complexity is easily avoidable. At least, I trust that people working on the committee wouldn't have missed a better way if there was one.</description>
		<content:encoded><![CDATA[<p>At the moment I still think rvalue references are a good thing. They are complex, yes, but I don&#8217;t think this complexity is easily avoidable. At least, I trust that people working on the committee wouldn&#8217;t have missed a better way if there was one.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
