{"id":5896,"date":"2024-11-17T10:10:38","date_gmt":"2024-11-17T02:10:38","guid":{"rendered":"http:\/\/blog.coolcoding.cn\/?p=5896"},"modified":"2024-11-17T10:28:13","modified_gmt":"2024-11-17T02:28:13","slug":"understanding-lvalues-and-rvalues-in-c-and-c","status":"publish","type":"post","link":"https:\/\/blog.coolcoding.cn\/?p=5896","title":{"rendered":"Understanding lvalues and rvalues in C and C++"},"content":{"rendered":"\n<p><a href=\"https:\/\/eli.thegreenplace.net\/2011\/12\/15\/understanding-lvalues-and-rvalues-in-c-and-c\"><strong>https:\/\/eli.thegreenplace.net\/2011\/12\/15\/understanding-lvalues-and-rvalues-in-c-and-c<\/strong><\/a><\/p>\n\n\n\n<p>The terms&nbsp;<em>lvalue<\/em>&nbsp;and&nbsp;<em>rvalue<\/em>&nbsp;are not something one runs into often in C\/C++ programming, but when one does, it&#8217;s usually not immediately clear what they mean. The most common place to run into these terms are in compiler error &amp; warning messages. For example, compiling the following with&nbsp;gcc:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int foo() {return 2;}\n\nint main()\n{\n    foo() = 2;\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p>You get:test.c: In function &#8216;main&#8217;: test.c:8:5: error: lvalue required as left operand of assignment<\/p>\n\n\n\n<p>True, this code is somewhat perverse and not something you&#8217;d write, but the error message mentions&nbsp;<em>lvalue<\/em>, which is not a term one usually finds in C\/C++ tutorials. Another example is compiling this code with&nbsp;g++:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int&amp; foo()\n{\n    return 2;\n}<\/code><\/pre>\n\n\n\n<p>Now the error is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>testcpp.cpp: In function 'int&amp; foo()':\ntestcpp.cpp:5:12: error: invalid initialization of non-const reference\nof type 'int&amp;' from an rvalue of type 'int'<\/code><\/pre>\n\n\n\n<p>Here again, the error mentions some mysterious&nbsp;<em>rvalue<\/em>. So what do&nbsp;<em>lvalue<\/em>&nbsp;and&nbsp;<em>rvalue<\/em>&nbsp;mean in C and C++? This is what I intend to explore in this article.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A simple definition<\/h3>\n\n\n\n<p>This section presents an intentionally simplified definition of&nbsp;<em>lvalues<\/em>&nbsp;and&nbsp;<em>rvalues<\/em>. The rest of the article will elaborate on this definition.<\/p>\n\n\n\n<p>An&nbsp;<em>lvalue<\/em>&nbsp;(<em>locator value<\/em>) represents an object that occupies some identifiable location in memory (i.e. has an address).<\/p>\n\n\n\n<p><em>rvalues<\/em>&nbsp;are defined by exclusion, by saying that every expression is either an&nbsp;<em>lvalue<\/em>&nbsp;or an&nbsp;<em>rvalue<\/em>. Therefore, from the above definition of&nbsp;<em>lvalue<\/em>, an&nbsp;<em>rvalue<\/em>&nbsp;is an expression that&nbsp;<em>does not<\/em>&nbsp;represent an object occupying some identifiable location in memory.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Basic examples<\/h3>\n\n\n\n<p>The terms as defined above may appear vague, which is why it&#8217;s important to see some simple examples right away.<\/p>\n\n\n\n<p>Let&#8217;s assume we have an integer variable defined and assigned to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int var;\nvar = 4;<\/code><\/pre>\n\n\n\n<p>An assignment expects an lvalue as its left operand, and&nbsp;var&nbsp;is an lvalue, because it is an object with an identifiable memory location. On the other hand, the following are invalid:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>4 = var;       \/\/ ERROR!\n(var + 1) = 4; \/\/ ERROR!<\/code><\/pre>\n\n\n\n<p>Neither the constant&nbsp;4, nor the expression&nbsp;var + 1&nbsp;are lvalues (which makes them rvalues). They&#8217;re not lvalues because both are temporary results of expressions, which don&#8217;t have an identifiable memory location (i.e. they can just reside in some temporary register for the duration of the computation). Therefore, assigning to them makes no semantic sense &#8211; there&#8217;s nowhere to assign to.<\/p>\n\n\n\n<p>So it should now be clear what the error message in the first code snippet means.&nbsp;foo&nbsp;returns a temporary value which is an rvalue. Attempting to assign to it is an error, so when seeing&nbsp;foo() = 2;&nbsp;the compiler complains that it expected to see an lvalue on the left-hand-side of the assignment statement.<\/p>\n\n\n\n<p>Not all assignments to results of function calls are invalid, however. For example, C++ references make this possible:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int globalvar = 20;\n\nint&amp; foo()\n{\n    return globalvar;\n}\n\nint main()\n{\n    foo() = 10;\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p>Here&nbsp;foo&nbsp;returns a reference,&nbsp;<em>which is an lvalue<\/em>, so it can be assigned to. Actually, the ability of C++ to return lvalues from functions is important for implementing some overloaded operators. One common example is overloading the brackets operator&nbsp;[]&nbsp;in classes that implement some kind of lookup access.&nbsp;std::map&nbsp;does this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>std::map&lt;int, float&gt; mymap;\nmymap&#91;10] = 5.6;<\/code><\/pre>\n\n\n\n<p>The assignment&nbsp;mymap[10]&nbsp;works because the non-const overload of&nbsp;std::map::operator[]&nbsp;returns a reference that can be assigned to.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Modifiable lvalues<\/h3>\n\n\n\n<p>Initially when lvalues were defined for C, it literally meant &#8220;values suitable for left-hand-side of assignment&#8221;. Later, however, when ISO C added the&nbsp;const&nbsp;keyword, this definition had to be refined. After all:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const int a = 10; \/\/ 'a' is an lvalue\na = 10;           \/\/ but it can't be assigned!<\/code><\/pre>\n\n\n\n<p>So a further refinement had to be added. Not all lvalues can be assigned to. Those that can are called&nbsp;<em>modifiable lvalues<\/em>. Formally, the C99 standard defines modifiable lvalues as:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>[&#8230;] an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Conversions between lvalues and rvalues<\/h3>\n\n\n\n<p>Generally speaking, language constructs operating on object values require rvalues as arguments. For example, the binary addition operator&nbsp;&#8216;+&#8217;&nbsp;takes two rvalues as arguments and returns an rvalue:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int a = 1;     \/\/ a is an lvalue\nint b = 2;     \/\/ b is an lvalue\nint c = a + b; \/\/ + needs rvalues, so a and b are converted to rvalues\n               \/\/ and an rvalue is returned<\/code><\/pre>\n\n\n\n<p>As we&#8217;ve seen earlier,&nbsp;a&nbsp;and&nbsp;b&nbsp;are both lvalues. Therefore, in the third line, they undergo an implicit&nbsp;<em>lvalue-to-rvalue conversion<\/em>. All lvalues that aren&#8217;t arrays, functions or of incomplete types can be converted thus to rvalues.<\/p>\n\n\n\n<p>What about the other direction? Can rvalues be converted to lvalues? Of course not! This would violate the very nature of an lvalue according to its definition&nbsp;<a href=\"https:\/\/eli.thegreenplace.net\/2011\/12\/15\/understanding-lvalues-and-rvalues-in-c-and-c#id6\">[1]<\/a>.<\/p>\n\n\n\n<p>This doesn&#8217;t mean that lvalues can&#8217;t be produced from rvalues by more explicit means. For example, the unary&nbsp;&#8216;*&#8217;&nbsp;(dereference) operator takes an rvalue argument but produces an lvalue as a result. Consider this valid code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int arr&#91;] = {1, 2};\nint* p = &amp;arr&#91;0];\n*(p + 1) = 10;   \/\/ OK: p + 1 is an rvalue, but *(p + 1) is an lvalue<\/code><\/pre>\n\n\n\n<p>Conversely, the unary address-of operator&nbsp;&#8216;&amp;&#8217;&nbsp;takes an lvalue argument and produces an rvalue:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int var = 10;\nint* bad_addr = &amp;(var + 1); \/\/ ERROR: lvalue required as unary '&amp;' operand\nint* addr = &amp;var;           \/\/ OK: var is an lvalue\n&amp;var = 40;                  \/\/ ERROR: lvalue required as left operand\n                            \/\/ of assignment<\/code><\/pre>\n\n\n\n<p>The ampersand plays another role in C++ &#8211; it allows to define reference types. These are called &#8220;lvalue references&#8221;. Non-const lvalue references cannot be assigned rvalues, since that would require an invalid rvalue-to-lvalue conversion:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>std::string&amp; sref = std::string();  \/\/ ERROR: invalid initialization of\n                                    \/\/ non-const reference of type\n                                    \/\/ 'std::string&amp;' from an rvalue of\n                                    \/\/ type 'std::string'<\/code><\/pre>\n\n\n\n<p>Constant lvalue references&nbsp;<em>can<\/em>&nbsp;be assigned rvalues. Since they&#8217;re constant, the value can&#8217;t be modified through the reference and hence there&#8217;s no problem of modifying an rvalue. This makes possible the very common C++ idiom of accepting values by constant references into functions, which avoids unnecessary copying and construction of temporary objects.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">CV-qualified rvalues<\/h3>\n\n\n\n<p>If we read carefully the portion of the C++ standard discussing lvalue-to-rvalue conversions&nbsp;<a href=\"https:\/\/eli.thegreenplace.net\/2011\/12\/15\/understanding-lvalues-and-rvalues-in-c-and-c#id7\">[2]<\/a>, we notice it says:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>An lvalue (3.10) of a non-function, non-array type T can be converted to an rvalue. [&#8230;] If T is a non-class type, the type of the rvalue is the cv-unqualified version of T. Otherwise, the type of the rvalue is T.<\/p>\n<\/blockquote>\n\n\n\n<p>What is this &#8220;cv-unqualified&#8221; thing?&nbsp;<em>CV-qualifier<\/em>&nbsp;is a term used to describe&nbsp;<em>const<\/em>&nbsp;and&nbsp;<em>volatile<\/em>&nbsp;type qualifiers.<\/p>\n\n\n\n<p>From section 3.9.3:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>Each type which is a cv-unqualified complete or incomplete object type or is void (3.9) has three corresponding cv-qualified versions of its type: a&nbsp;<em>const-qualified<\/em>&nbsp;version, a&nbsp;<em>volatile-qualified<\/em>&nbsp;version, and a&nbsp;<em>const-volatile-qualified<\/em>&nbsp;version. [&#8230;] The cv-qualified or cv-unqualified versions of a type are distinct types; however, they shall have the same representation and alignment requirements (3.9)<\/p>\n<\/blockquote>\n\n\n\n<p>But what has this got to do with rvalues? Well, in C, rvalues never have cv-qualified types. Only lvalues do. In C++, on the other hand, class rvalues can have cv-qualified types, but built-in types (like&nbsp;int) can&#8217;t. Consider this example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;iostream&gt;\n\nclass A {\npublic:\n    void foo() const { std::cout &lt;&lt; \"A::foo() const\\n\"; }\n    void foo() { std::cout &lt;&lt; \"A::foo()\\n\"; }\n};\n\nA bar() { return A(); }\nconst A cbar() { return A(); }\n\n\nint main()\n{\n    bar().foo();  \/\/ calls foo\n    cbar().foo(); \/\/ calls foo const\n}<\/code><\/pre>\n\n\n\n<p>The second call in&nbsp;main&nbsp;actually calls the&nbsp;foo () const&nbsp;method of&nbsp;A, because the type returned by&nbsp;cbar&nbsp;is&nbsp;const A, which is distinct from&nbsp;A. This is exactly what&#8217;s meant by the last sentence in the quote mentioned earlier. Note also that the return value from&nbsp;cbar&nbsp;is an rvalue. So this is an example of a cv-qualified rvalue in action.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Rvalue references (C++11)<\/h3>\n\n\n\n<p>Rvalue references and the related concept of&nbsp;<em>move semantics<\/em>&nbsp;is one of the most powerful new features the C++11 standard introduces to the language. A full discussion of the feature is way beyond the scope of this humble article&nbsp;<a href=\"https:\/\/eli.thegreenplace.net\/2011\/12\/15\/understanding-lvalues-and-rvalues-in-c-and-c#id8\">[3]<\/a>, but I still want to provide a simple example, because I think it&#8217;s a good place to demonstrate how an understanding of what lvalues and rvalues are aids our ability to reason about non-trivial language concepts.<\/p>\n\n\n\n<p>I&#8217;ve just spent a good part of this article explaining that one of the main differences between lvalues and rvalues is that lvalues can be modified, and rvalues can&#8217;t. Well, C++11 adds a crucial twist to this distinction, by allowing us to have references to rvalues and thus modify them, in some special circumstances.<\/p>\n\n\n\n<p>As an example, consider a simplistic implementation of a dynamic &#8220;integer vector&#8221;. I&#8217;m showing just the relevant methods here:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class Intvec\n{\npublic:\n    explicit Intvec(size_t num = 0)\n        : m_size(num), m_data(new int&#91;m_size])\n    {\n        log(\"constructor\");\n    }\n\n    ~Intvec()\n    {\n        log(\"destructor\");\n        if (m_data) {\n            delete&#91;] m_data;\n            m_data = 0;\n        }\n    }\n\n    Intvec(const Intvec&amp; other)\n        : m_size(other.m_size), m_data(new int&#91;m_size])\n    {\n        log(\"copy constructor\");\n        for (size_t i = 0; i &lt; m_size; ++i)\n            m_data&#91;i] = other.m_data&#91;i];\n    }\n\n    Intvec&amp; operator=(const Intvec&amp; other)\n    {\n        log(\"copy assignment operator\");\n        Intvec tmp(other);\n        std::swap(m_size, tmp.m_size);\n        std::swap(m_data, tmp.m_data);\n        return *this;\n    }\nprivate:\n    void log(const char* msg)\n    {\n        cout &lt;&lt; \"&#91;\" &lt;&lt; this &lt;&lt; \"] \" &lt;&lt; msg &lt;&lt; \"\\n\";\n    }\n\n    size_t m_size;\n    int* m_data;\n};<\/code><\/pre>\n\n\n\n<p>So, we have the usual constructor, destructor, copy constructor and copy assignment operator&nbsp;<a href=\"https:\/\/eli.thegreenplace.net\/2011\/12\/15\/understanding-lvalues-and-rvalues-in-c-and-c#id9\">[4]<\/a>&nbsp;defined, all using a logging function to let us know when they&#8217;re actually called.<\/p>\n\n\n\n<p>Let&#8217;s run some simple code, which copies the contents of&nbsp;v1&nbsp;into&nbsp;v2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Intvec v1(20);\nIntvec v2;\n\ncout &lt;&lt; \"assigning lvalue...\\n\";\nv2 = v1;\ncout &lt;&lt; \"ended assigning lvalue...\\n\";<\/code><\/pre>\n\n\n\n<p>What this prints is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>assigning lvalue...\n&#91;0x28fef8] copy assignment operator\n&#91;0x28fec8] copy constructor\n&#91;0x28fec8] destructor\nended assigning lvalue...<\/code><\/pre>\n\n\n\n<p>Makes sense &#8211; this faithfully represents what&#8217;s going on inside&nbsp;operator=. But suppose that we want to assign some rvalue to&nbsp;v2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cout &lt;&lt; \"assigning rvalue...\\n\";\nv2 = Intvec(33);\ncout &lt;&lt; \"ended assigning rvalue...\\n\";<\/code><\/pre>\n\n\n\n<p>Although here I just assign a freshly constructed vector, it&#8217;s just a demonstration of a more general case where some temporary rvalue is being built and then assigned to&nbsp;v2&nbsp;(this can happen for some function returning a vector, for example). What gets printed now is this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>assigning rvalue...\n&#91;0x28ff08] constructor\n&#91;0x28fef8] copy assignment operator\n&#91;0x28fec8] copy constructor\n&#91;0x28fec8] destructor\n&#91;0x28ff08] destructor\nended assigning rvalue...<\/code><\/pre>\n\n\n\n<p>Ouch, this looks like a lot of work. In particular, it has one extra pair of constructor\/destructor calls to create and then destroy the temporary object. And this is a shame, because inside the copy assignment operator,&nbsp;<em>another<\/em>&nbsp;temporary copy is being created and destroyed. That&#8217;s extra work, for nothing.<\/p>\n\n\n\n<p>Well, no more. C++11 gives us rvalue references with which we can implement &#8220;move semantics&#8221;, and in particular a &#8220;move assignment operator&#8221;&nbsp;<a href=\"https:\/\/eli.thegreenplace.net\/2011\/12\/15\/understanding-lvalues-and-rvalues-in-c-and-c#id10\">[5]<\/a>. Let&#8217;s add another&nbsp;operator=&nbsp;to&nbsp;Intvec:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Intvec&amp; operator=(Intvec&amp;&amp; other)\n{\n    log(\"move assignment operator\");\n    std::swap(m_size, other.m_size);\n    std::swap(m_data, other.m_data);\n    return *this;\n}<\/code><\/pre>\n\n\n\n<p>The&nbsp;&amp;&amp;&nbsp;syntax is the new&nbsp;<em>rvalue reference<\/em>. It does exactly what it sounds it does &#8211; gives us a reference to an rvalue, which is going to be destroyed after the call. We can use this fact to just &#8220;steal&#8221; the internals of the rvalue &#8211; it won&#8217;t need them anyway! This prints:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>assigning rvalue...\n&#91;0x28ff08] constructor\n&#91;0x28fef8] move assignment operator\n&#91;0x28ff08] destructor\nended assigning rvalue...<\/code><\/pre>\n\n\n\n<p>What happens here is that our new move assignment operator is invoked since an rvalue gets assigned to&nbsp;v2. The constructor and destructor calls are still needed for the temporary object that&#8217;s created by&nbsp;Intvec(33), but another temporary inside the assignment operator is no longer needed. The operator simply switches the rvalue&#8217;s internal buffer with its own, arranging it so the rvalue&#8217;s destructor will release our object&#8217;s own buffer, which is no longer used. Neat.<\/p>\n\n\n\n<p>I&#8217;ll just mention once again that this example is only the tip of the iceberg on move semantics and rvalue references. As you can probably guess, it&#8217;s a complex subject with a lot of special cases and gotchas to consider. My point here was to demonstrate a very interesting application of the difference between lvalues and rvalues in C++. The compiler obviously knows when some entity is an rvalue, and can arrange to invoke the correct constructor at compile time.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusion<\/h3>\n\n\n\n<p>One can write a lot of C++ code without being concerned with the issue of rvalues vs. lvalues, dismissing them as weird compiler jargon in certain error messages. However, as this article aimed to show, getting a better grasp of this topic can aid in a deeper understanding of certain C++ code constructs, and make parts of the C++ spec and discussions between language experts more intelligible.<\/p>\n\n\n\n<p>Also, in the new C++ spec this topic becomes even more important, because C++11&#8217;s introduction of rvalue references and move semantics. To really grok this new feature of the language, a solid understanding of what rvalues and lvalues are becomes crucial.<\/p>\n\n\n\n<!--nextpage-->\n\n\n\n<p>\u6211\u4eec\u5728 C\/C++ \u7f16\u7a0b\u4e2d\u5e76\u4e0d\u4f1a\u7ecf\u5e38\u7528\u5230&nbsp;<em>\u5de6\u503c (lvalue)<\/em>&nbsp;\u548c&nbsp;<em>\u53f3\u503c (rvalue)<\/em>&nbsp;\u4e24\u4e2a\u672f\u8bed\u3002\u7136\u800c\u4e00\u65e6\u9047\u89c1\uff0c\u53c8\u5e38\u5e38\u4e0d\u6e05\u695a\u5b83\u4eec\u7684\u542b\u4e49\u3002\u6700\u53ef\u80fd\u51fa\u73b0\u4e24\u8fd9\u4e2a\u672f\u8bed\u7684\u5730\u65b9\u662f\u5728\u7f16\u8bd1\u9519\u8bef\u6216\u8b66\u544a\u7684\u4fe1\u606f\u4e2d\u3002\u4f8b\u5982\uff0c\u4f7f\u7528&nbsp;<code>gcc<\/code>&nbsp;\u7f16\u8bd1\u4ee5\u4e0b\u4ee3\u7801\u65f6\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<\/td><td>int foo() {return 2;}<br><br>int main()<br>{<br>foo() = 2;<br><br>return 0;<br>}<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u4f60\u4f1a\u5f97\u5230\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<\/td><td>test.c: In function &#8216;main&#8217;:<br>test.c:8:5: error: lvalue required as left operand of assignment<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u6ca1\u9519\uff0c\u8fd9\u4e2a\u4f8b\u5b50\u6709\u70b9\u5938\u5f20\uff0c\u4e0d\u50cf\u662f\u4f60\u80fd\u5199\u51fa\u6765\u7684\u4ee3\u7801\u3002\u4e0d\u8fc7\u9519\u8bef\u4fe1\u606f\u4e2d\u63d0\u5230\u4e86\u5de6\u503c (lvalue)\u3002\u53e6\u4e00\u4e2a\u4f8b\u5b50\u662f\u5f53\u4f60\u7528&nbsp;<code>g++<\/code>&nbsp;\u7f16\u8bd1\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<\/td><td>int&amp; foo()<br>{<br>return 2;<br>}<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u73b0\u5728\u9519\u8bef\u4fe1\u606f\u662f\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<\/td><td>testcpp.cpp: In function &#8216;int&amp; foo()&#8217;:<br>testcpp.cpp:5:12: error: invalid initialization of non-const reference of type &#8216;int&amp;&#8217; from an rvalue of type &#8216;int&#8217;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u540c\u6837\u7684\uff0c\u9519\u8bef\u4fe1\u606f\u4e2d\u63d0\u5230\u4e86\u672f\u8bed\u53f3\u503c (rvalue)\u3002\u90a3\u4e48\uff0c\u5728 C \u548c C++ \u4e2d\uff0c<em>\u5de6\u503c<\/em>&nbsp;\u548c&nbsp;<em>\u53f3\u503c<\/em>&nbsp;\u5230\u5e95\u662f\u4ec0\u4e48\u610f\u601d\u5462\uff1f\u6211\u8fd9\u7bc7\u6587\u7ae0\u5c06\u4f1a\u8be6\u7ec6\u89e3\u91ca\u3002<a><\/a><\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"\u7b80\u5355\u7684\u5b9a\u4e49\"><a href=\"https:\/\/nettee.github.io\/posts\/2018\/Understanding-lvalues-and-rvalues-in-C-and-C\/#%E7%AE%80%E5%8D%95%E7%9A%84%E5%AE%9A%E4%B9%89\"><\/a>\u7b80\u5355\u7684\u5b9a\u4e49<\/h1>\n\n\n\n<p>\u8fd9\u91cc\u6211\u6545\u610f\u7ed9\u51fa\u4e86\u4e00\u4e2a&nbsp;<em>\u5de6\u503c<\/em>&nbsp;\u548c&nbsp;<em>\u53f3\u503c<\/em>&nbsp;\u7684\u7b80\u5316\u7248\u5b9a\u4e49\u3002\u6587\u7ae0\u5269\u4e0b\u7684\u90e8\u5206\u8fd8\u4f1a\u8fdb\u884c\u8be6\u7ec6\u89e3\u91ca\u3002<\/p>\n\n\n\n<p><em>\u5de6\u503c (lvalue, locator value)<\/em>&nbsp;\u8868\u793a\u4e86\u4e00\u4e2a\u5360\u636e\u5185\u5b58\u4e2d\u67d0\u4e2a\u53ef\u8bc6\u522b\u7684\u4f4d\u7f6e\uff08\u4e5f\u5c31\u662f\u4e00\u4e2a\u5730\u5740\uff09\u7684\u5bf9\u8c61\u3002<\/p>\n\n\n\n<p><em>\u53f3\u503c (rvalue)<\/em>&nbsp;\u5219\u4f7f\u7528\u6392\u9664\u6cd5\u6765\u5b9a\u4e49\u3002\u4e00\u4e2a\u8868\u8fbe\u5f0f\u4e0d\u662f&nbsp;<em>\u5de6\u503c<\/em>&nbsp;\u5c31\u662f&nbsp;<em>\u53f3\u503c<\/em>&nbsp;\u3002 \u90a3\u4e48\uff0c\u53f3\u503c\u662f\u4e00\u4e2a&nbsp;<em>\u4e0d<\/em>&nbsp;\u8868\u793a\u5185\u5b58\u4e2d\u67d0\u4e2a\u53ef\u8bc6\u522b\u4f4d\u7f6e\u7684\u5bf9\u8c61\u7684\u8868\u8fbe\u5f0f\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"\u4e3e\u4f8b\"><a href=\"https:\/\/nettee.github.io\/posts\/2018\/Understanding-lvalues-and-rvalues-in-C-and-C\/#%E4%B8%BE%E4%BE%8B\"><\/a>\u4e3e\u4f8b<\/h1>\n\n\n\n<p>\u4e0a\u9762\u7684\u672f\u8bed\u5b9a\u4e49\u663e\u5f97\u6709\u4e9b\u6a21\u7cca\uff0c\u8fd9\u65f6\u5019\u6211\u4eec\u5c31\u9700\u8981\u9a6c\u4e0a\u770b\u4e00\u4e9b\u4f8b\u5b50\u3002\u6211\u4eec\u5047\u8bbe\u5b9a\u4e49\u5e76\u8d4b\u503c\u4e86\u4e00\u4e2a\u6574\u5f62\u53d8\u91cf\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<\/td><td>int var;<br>var = 4;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u8d4b\u503c\u64cd\u4f5c\u9700\u8981\u5de6\u64cd\u4f5c\u6570\u662f\u4e00\u4e2a\u5de6\u503c\u3002<code>var<\/code>&nbsp;\u662f\u4e00\u4e2a\u6709\u5185\u5b58\u4f4d\u7f6e\u7684\u5bf9\u8c61\uff0c\u56e0\u6b64\u5b83\u662f\u5de6\u503c\u3002\u7136\u800c\uff0c\u4e0b\u9762\u7684\u5199\u6cd5\u5219\u662f\u9519\u7684\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<\/td><td>4 = var; \/\/ \u9519\u8bef\uff01<br>(var + 1) = 4; \/\/ \u9519\u8bef\uff01<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u5e38\u91cf&nbsp;<code>4<\/code>&nbsp;\u548c\u8868\u8fbe\u5f0f&nbsp;<code>var + 1<\/code>&nbsp;\u90fd\u4e0d\u662f\u5de6\u503c\uff08\u4e5f\u5c31\u662f\u8bf4\uff0c\u5b83\u4eec\u662f\u53f3\u503c\uff09\uff0c\u56e0\u4e3a\u5b83\u4eec\u90fd\u662f\u8868\u8fbe\u5f0f\u7684\u4e34\u65f6\u7ed3\u679c\uff0c\u800c\u6ca1\u6709\u53ef\u8bc6\u522b\u7684\u5185\u5b58\u4f4d\u7f6e\uff08\u4e5f\u5c31\u662f\u8bf4\uff0c\u53ea\u5b58\u5728\u4e8e\u8ba1\u7b97\u8fc7\u7a0b\u4e2d\u7684\u6bcf\u4e2a\u4e34\u65f6\u5bc4\u5b58\u5668\u4e2d\uff09\u3002\u56e0\u6b64\uff0c\u8d4b\u503c\u7ed9\u5b83\u4eec\u662f\u6ca1\u6709\u4efb\u4f55\u8bed\u4e49\u4e0a\u7684\u610f\u4e49\u7684\u2014\u2014\u6211\u4eec\u8d4b\u503c\u5230\u4e86\u4e00\u4e2a\u4e0d\u5b58\u5728\u7684\u4f4d\u7f6e\u3002<\/p>\n\n\n\n<p>\u90a3\u4e48\uff0c\u6211\u4eec\u5c31\u80fd\u7406\u89e3\u7b2c\u4e00\u4e2a\u4ee3\u7801\u7247\u6bb5\u4e2d\u7684\u9519\u8bef\u4fe1\u606f\u7684\u542b\u4e49\u4e86\u3002<code>foo<\/code>&nbsp;\u8fd4\u56de\u7684\u662f\u4e00\u4e2a\u4e34\u65f6\u7684\u503c\u3002\u5b83\u662f\u4e00\u4e2a\u53f3\u503c\uff0c\u8d4b\u503c\u7ed9\u5b83\u662f\u9519\u8bef\u7684\u3002\u56e0\u6b64\u5f53\u7f16\u8bd1\u5668\u770b\u5230&nbsp;<code>foo() = 2<\/code>&nbsp;\u65f6\uff0c\u4f1a\u62a5\u9519\u2014\u2014\u8d4b\u503c\u8bed\u53e5\u7684\u5de6\u8fb9\u5e94\u5f53\u662f\u4e00\u4e2a\u5de6\u503c\u3002<\/p>\n\n\n\n<p>\u7136\u800c\uff0c\u7ed9\u51fd\u6570\u8fd4\u56de\u7684\u7ed3\u679c\u8d4b\u503c\uff0c\u4e0d\u4e00\u5b9a\u603b\u662f\u9519\u8bef\u7684\u64cd\u4f5c\u3002\u4f8b\u5982\uff0cC++ \u7684\u5f15\u7528\u8ba9\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5199\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>11<br>12<\/td><td>int globalvar = 20;<br><br>int&amp; foo()<br>{<br>return globalvar;<br>}<br><br>int main()<br>{<br>foo() = 10;<br>return 0;<br>}<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u8fd9\u91cc&nbsp;<code>foo<\/code>&nbsp;\u8fd4\u56de\u4e00\u4e2a\u5f15\u7528\u3002<strong>\u5f15\u7528\u4e00\u4e2a\u5de6\u503c<\/strong>\uff0c\u56e0\u6b64\u53ef\u4ee5\u8d4b\u503c\u7ed9\u5b83\u3002\u5b9e\u9645\u4e0a\uff0cC++ \u4e2d\u51fd\u6570\u53ef\u4ee5\u8fd4\u56de\u5de6\u503c\u7684\u529f\u80fd\u5bf9\u5b9e\u73b0\u4e00\u4e9b\u91cd\u8f7d\u7684\u64cd\u4f5c\u7b26\u975e\u5e38\u91cd\u8981\u3002\u4e00\u4e2a\u5e38\u89c1\u7684\u4f8b\u5b50\u5c31\u662f\u91cd\u8f7d\u65b9\u62ec\u53f7\u64cd\u4f5c\u7b26&nbsp;<code>[]<\/code>\uff0c\u6765\u5b9e\u73b0\u4e00\u4e9b\u67e5\u627e\u8bbf\u95ee\u7684\u64cd\u4f5c\uff0c\u5982&nbsp;<code>std::map<\/code>&nbsp;\u4e2d\u7684\u65b9\u62ec\u53f7\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<\/td><td>std::map&lt;int, float&gt; mymap;<br>mymap[10] = 5.6;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u4e4b\u6240\u4ee5\u80fd\u8d4b\u503c\u7ed9&nbsp;<code>mymap[10]<\/code>\uff0c\u662f\u56e0\u4e3a&nbsp;<code>std::map::operator[]<\/code>&nbsp;\u7684\u91cd\u8f7d\u8fd4\u56de\u7684\u662f\u4e00\u4e2a\u53ef\u8d4b\u503c\u7684\u5f15\u7528\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"\u53ef\u4fee\u6539\u7684\u5de6\u503c\"><a href=\"https:\/\/nettee.github.io\/posts\/2018\/Understanding-lvalues-and-rvalues-in-C-and-C\/#%E5%8F%AF%E4%BF%AE%E6%94%B9%E7%9A%84%E5%B7%A6%E5%80%BC\"><\/a>\u53ef\u4fee\u6539\u7684\u5de6\u503c<\/h1>\n\n\n\n<p>\u5de6\u503c\u4e00\u5f00\u59cb\u5728 C \u4e2d\u5b9a\u4e49\u4e3a\u201c\u53ef\u4ee5\u51fa\u73b0\u5728\u8d4b\u503c\u64cd\u4f5c\u5de6\u8fb9\u7684\u503c\u201d\u3002\u7136\u800c\uff0c\u5f53 ISO C \u52a0\u5165&nbsp;<code>const<\/code>&nbsp;\u5173\u952e\u5b57\u540e\uff0c\u8fd9\u4e2a\u5b9a\u4e49\u4fbf\u4e0d\u518d\u6210\u7acb\u3002\u6bd5\u7adf\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<\/td><td>const int a = 10; \/\/ &#8216;a&#8217; \u662f\u5de6\u503c<br>a = 10; \/\/ \u4f46\u4e0d\u53ef\u4ee5\u8d4b\u503c\u7ed9\u5b83\uff01<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u4e8e\u662f\u5b9a\u4e49\u9700\u8981\u7ee7\u7eed\u7cbe\u5316\u3002\u4e0d\u662f\u6240\u6709\u7684\u5de6\u503c\u90fd\u53ef\u4ee5\u88ab\u8d4b\u503c\u3002\u53ef\u8d4b\u503c\u7684\u5de6\u503c\u88ab\u79f0\u4e3a&nbsp;<em>\u53ef\u4fee\u6539\u5de6\u503c (modifiable lvalues)<\/em>&nbsp;\u3002C99\u6807\u51c6\u5b9a\u4e49\u53ef\u4fee\u6539\u5de6\u503c\u4e3a\uff1a<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>[\u2026] \u53ef\u4fee\u6539\u5de6\u503c\u662f\u7279\u6b8a\u7684\u5de6\u503c\uff0c\u4e0d\u542b\u6709\u6570\u7ec4\u7c7b\u578b\u3001\u4e0d\u5b8c\u6574\u7c7b\u578b\u3001const \u4fee\u9970\u7684\u7c7b\u578b\u3002\u5982\u679c\u5b83\u662f&nbsp;<code>struct<\/code>&nbsp;\u6216&nbsp;<code>union<\/code>\uff0c\u5b83\u7684\u6210\u5458\u90fd\uff08\u9012\u5f52\u5730\uff09\u4e0d\u5e94\u542b\u6709 const \u4fee\u9970\u7684\u7c7b\u578b\u3002<\/p>\n<\/blockquote>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"\u5de6\u503c\u4e0e\u53f3\u503c\u95f4\u7684\u8f6c\u6362\"><a href=\"https:\/\/nettee.github.io\/posts\/2018\/Understanding-lvalues-and-rvalues-in-C-and-C\/#%E5%B7%A6%E5%80%BC%E4%B8%8E%E5%8F%B3%E5%80%BC%E9%97%B4%E7%9A%84%E8%BD%AC%E6%8D%A2\"><\/a>\u5de6\u503c\u4e0e\u53f3\u503c\u95f4\u7684\u8f6c\u6362<\/h1>\n\n\n\n<p>\u901a\u5e38\u6765\u8bf4\uff0c\u8ba1\u7b97\u5bf9\u8c61\u7684\u503c\u7684\u8bed\u8a00\u6210\u5206\uff0c\u90fd\u4f7f\u7528\u53f3\u503c\u4f5c\u4e3a\u53c2\u6570\u3002\u4f8b\u5982\uff0c\u4e24\u5143\u52a0\u6cd5\u64cd\u4f5c\u7b26&nbsp;<code>'+'<\/code>&nbsp;\u5c31\u9700\u8981\u4e24\u4e2a\u53f3\u503c\u53c2\u6570\uff0c\u5e76\u8fd4\u56de\u4e00\u4e2a\u53f3\u503c\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<\/td><td>int a = 1; \/\/ a \u662f\u5de6\u503c<br>int b = 2; \/\/ b \u662f\u5de6\u503c<br>int c = a + b; \/\/ + \u9700\u8981\u53f3\u503c\uff0c\u6240\u4ee5 a \u548c b \u88ab\u8f6c\u6362\u6210\u53f3\u503c<br>\/\/ + \u8fd4\u56de\u53f3\u503c<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u5728\u4f8b\u5b50\u4e2d\uff0c<code>a<\/code>&nbsp;\u548c&nbsp;<code>b<\/code>&nbsp;\u90fd\u662f\u5de6\u503c\u3002\u56e0\u6b64\uff0c\u5728\u7b2c\u4e09\u884c\u4e2d\uff0c\u5b83\u4eec\u7ecf\u5386\u4e86\u9690\u5f0f\u7684&nbsp;<em>\u5de6\u503c\u5230\u53f3\u503c\u8f6c\u6362<\/em>&nbsp;\u3002\u9664\u4e86\u6570\u7ec4\u3001\u51fd\u6570\u3001\u4e0d\u5b8c\u6574\u7c7b\u578b\u7684\u6240\u6709\u5de6\u503c\u90fd\u53ef\u4ee5\u8f6c\u6362\u4e3a\u53f3\u503c\u3002<\/p>\n\n\n\n<p>\u90a3\u53f3\u503c\u80fd\u5426\u8f6c\u6362\u4e3a\u5de6\u503c\u5462\uff1f\u5f53\u7136\u4e0d\u80fd\uff01\u6839\u636e\u5de6\u503c\u7684\u5b9a\u4e49\uff0c\u8fd9\u8fdd\u53cd\u4e86\u5de6\u503c\u7684\u672c\u8d28\u3002\u3010\u6ce81\uff1a\u53f3\u503c\u53ef\u4ee5\u663e\u5f0f\u5730\u8d4b\u503c\u7ed9\u5de6\u503c\u3002\u4e4b\u6240\u4ee5\u6ca1\u6709\u9690\u5f0f\u7684\u8f6c\u6362\uff0c\u662f\u56e0\u4e3a\u53f3\u503c\u4e0d\u80fd\u4f7f\u7528\u5728\u5de6\u503c\u5e94\u5f53\u51fa\u73b0\u7684\u4f4d\u7f6e\u3002\u3011<\/p>\n\n\n\n<p>\u4e0d\u8fc7\uff0c\u53f3\u503c\u53ef\u4ee5\u901a\u8fc7\u4e00\u4e9b\u66f4\u663e\u5f0f\u7684\u65b9\u6cd5\u4ea7\u751f\u5de6\u503c\u3002\u4f8b\u5982\uff0c\u4e00\u5143\u89e3\u5f15\u7528\u64cd\u4f5c\u7b26&nbsp;<code>'*'<\/code>&nbsp;\u9700\u8981\u4e00\u4e2a\u53f3\u503c\u53c2\u6570\uff0c\u4f46\u8fd4\u56de\u4e00\u4e2a\u5de6\u503c\u7ed3\u679c\u3002\u8003\u8651\u8fd9\u6837\u7684\u4ee3\u7801\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<\/td><td>int arr[] = {1, 2};<br>int* p = &amp;arr[0];<br>*(p + 1) = 10; \/\/ \u6b63\u786e: p + 1 \u662f\u53f3\u503c\uff0c\u4f46 *(p + 1) \u662f\u5de6\u503c<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u76f8\u53cd\u5730\uff0c\u4e00\u5143\u53d6\u5730\u5740\u64cd\u4f5c\u7b26&nbsp;<code>'&amp;'<\/code>&nbsp;\u9700\u8981\u4e00\u4e2a\u5de6\u503c\u53c2\u6570\uff0c\u8fd4\u56de\u4e00\u4e2a\u53f3\u503c\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<\/td><td>int var = 10;<br>int* bad_addr = &amp;(var + 1); \/\/ \u9519\u8bef: \u4e00\u5143 &#8216;&amp;&#8217; \u64cd\u4f5c\u7b26\u9700\u8981\u5de6\u503c\u53c2\u6570<br>int* addr = &amp;var; \/\/ \u6b63\u786e: var \u662f\u5de6\u503c<br>&amp;var = 40; \/\/ \u9519\u8bef: \u8d4b\u503c\u64cd\u4f5c\u7684\u5de6\u64cd\u4f5c\u6570\u9700\u8981\u662f\u5de6\u503c<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u5728 C++ \u4e2d&nbsp;<code>'&amp;'<\/code>&nbsp;\u7b26\u53f7\u8fd8\u6709\u53e6\u4e00\u4e2a\u529f\u80fd\u2014\u2014\u5b9a\u4e49\u5f15\u7528\u7c7b\u578b\u3002\u5f15\u7528\u7c7b\u578b\u53c8\u53eb\u505a\u201c\u5de6\u503c\u5f15\u7528\u201d\u3002\u56e0\u6b64\uff0c\u4e0d\u80fd\u5c06\u4e00\u4e2a\u53f3\u503c\u8d4b\u503c\u7ed9\uff08\u975e\u5e38\u91cf\u7684\uff09\u5de6\u503c\u5f15\u7528\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<\/td><td>std::string&amp; sref = std::string(); \/\/ \u9519\u8bef: \u975e\u5e38\u91cf\u7684\u5f15\u7528 &#8216;std::string&amp;&#8217; \u9519\u8bef\u5730\u4f7f\u7528\u53f3\u503c &#8216;std::string` \u521d\u59cb\u5316<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><em>\u5e38\u91cf\u7684<\/em>&nbsp;\u5de6\u503c\u5f15\u7528\u53ef\u4ee5\u4f7f\u7528\u53f3\u503c\u8d4b\u503c\u3002\u56e0\u4e3a\u4f60\u65e0\u6cd5\u901a\u8fc7\u5e38\u91cf\u7684\u5f15\u7528\u4fee\u6539\u53d8\u91cf\u7684\u503c\uff0c\u4e5f\u5c31\u4e0d\u4f1a\u51fa\u73b0\u4fee\u6539\u4e86\u53f3\u503c\u7684\u60c5\u51b5\u3002\u8fd9\u4e5f\u4f7f\u5f97 C++ \u4e2d\u4e00\u4e2a\u5e38\u89c1\u7684\u4e60\u60ef\u6210\u4e3a\u53ef\u80fd\uff1a\u51fd\u6570\u7684\u53c2\u6570\u4f7f\u7528\u5e38\u91cf\u5f15\u7528\u63a5\u6536\u53c2\u6570\uff0c\u907f\u514d\u521b\u5efa\u4e0d\u5fc5\u8981\u7684\u4e34\u65f6\u5bf9\u8c61\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"CV-\u9650\u5b9a\u7684\u53f3\u503c\"><a href=\"https:\/\/nettee.github.io\/posts\/2018\/Understanding-lvalues-and-rvalues-in-C-and-C\/#CV-%E9%99%90%E5%AE%9A%E7%9A%84%E5%8F%B3%E5%80%BC\"><\/a>CV \u9650\u5b9a\u7684\u53f3\u503c<\/h1>\n\n\n\n<p>\u5982\u679c\u6211\u4eec\u4ed4\u7ec6\u9605\u8bfb C++ \u6807\u51c6\u4e2d\u5173\u4e8e\u5de6\u503c\u5230\u53f3\u503c\u7684\u8f6c\u6362\u7684\u90e8\u5206\u3010\u6ce82\uff1a\u5728\u65b0\u7684 C++11 \u6807\u51c6\u8349\u7a3f\u7684\u7b2c 4.1 \u8282\u3011\uff0c\u6211\u4eec\u4f1a\u53d1\u73b0\uff1a<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>\u4e00\u4e2a\u975e\u51fd\u6570\u3001\u975e\u6570\u7ec4\u7684\u7c7b\u578b T \u7684\u5de6\u503c\u53ef\u4ee5\u8f6c\u6362\u4e3a\u53f3\u503c\u3002 [\u2026] \u5982\u679c T \u4e0d\u662f\u7c7b\u7c7b\u578b\u3010\u8bd1\u6ce8\uff1a\u7c7b\u7c7b\u578b\u5373 C++ \u4e2d\u4f7f\u7528\u7c7b\u5b9a\u4e49\u7684\u7c7b\u578b\uff0c\u533a\u522b\u4e0e\u5185\u7f6e\u7c7b\u578b\u3011\uff0c\u8f6c\u6362\u540e\u7684\u53f3\u503c\u7684\u7c7b\u578b\u662f T \u7684 \u672a\u9650\u5b9a CV \u7684\u7248\u672c (cv-unqualified version of T)\u3002\u5176\u4ed6\u60c5\u51b5\u4e0b\uff0c\u8f6c\u6362\u540e\u7684\u53f3\u503c\u7c7b\u578b\u5c31\u662f T \u672c\u8eab\u3002<\/p>\n<\/blockquote>\n\n\n\n<p>\u4ec0\u4e48\u53eb\u505a \u201c\u672a\u9650\u5b9a CV\u201d (cv-unqualified) \u5462\uff1f&nbsp;<em>CV \u9650\u5b9a\u7b26<\/em>&nbsp;\u8fd9\u4e2a\u672f\u8bed\u6307\u7684\u662f&nbsp;<em>const<\/em>&nbsp;\u548c&nbsp;<em>volatile<\/em>&nbsp;\u4e24\u4e2a\u7c7b\u578b\u9650\u5b9a\u7b26\u3002C++ \u6807\u51c6\u7684 3.9.3 \u8282\u5199\u5230\uff1a<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>\u6bcf\u4e2a\u7c7b\u578b\u90fd\u6709\u4e09\u4e2a\u5bf9\u5e94\u7684 CV-\u9650\u5b9a\u7c7b\u578b\u7248\u672c\uff1a&nbsp;<em>const \u9650\u5b9a<\/em>&nbsp;\u3001&nbsp;<em>volatile \u9650\u5b9a<\/em>&nbsp;\u548c&nbsp;<em>const-volatile \u9650\u5b9a<\/em>&nbsp;\u7248\u672c\u3002\u6709\u6216\u65e0 CV \u9650\u5b9a\u7684\u4e0d\u540c\u7248\u672c\u7684\u7c7b\u578b\u662f\u4e0d\u540c\u7684\u7c7b\u578b\uff0c\u4f46\u5199\u6cd5\u548c\u8d4b\u503c\u9700\u6c42\u90fd\u662f\u76f8\u540c\u7684\u3002<\/p>\n<\/blockquote>\n\n\n\n<p>\u90a3\u4e48\uff0c\u8fd9\u4e9b\u53c8\u548c\u53f3\u503c\u6709\u4ec0\u4e48\u5173\u7cfb\u5462\uff1f\u5728 C \u4e2d\uff0c\u53ea\u6709\u5de6\u503c\u6709 CV \u9650\u5b9a\u7684\u7c7b\u578b\uff0c\u800c\u53f3\u503c\u4ece\u6765\u6ca1\u6709\u3002\u800c\u5728 C++ \u4e2d\uff0c\u7c7b\u53f3\u503c\u53ef\u4ee5\u6709 CV \u9650\u5b9a\u7684\u7c7b\u578b\uff0c\u4f46\u5185\u7f6e\u7c7b\u578b (\u5982&nbsp;<code>int<\/code>) \u5219\u6ca1\u6709\u3002\u8003\u8651\u4e0b\u9762\u7684\u4f8b\u5b50\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<\/td><td>#include &lt;iostream&gt;<br><br>class A {<br>public:<br>void foo() const { std::cout &lt;&lt; &#8220;A::foo() const\\n&#8221;; }<br>void foo() { std::cout &lt;&lt; &#8220;A::foo()\\n&#8221;; }<br>};<br><br>A bar() { return A(); }<br>const A cbar() { return A(); }<br><br><br>int main()<br>{<br>bar().foo(); \/\/ calls foo<br>cbar().foo(); \/\/ calls foo const<br>}<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><code>main<\/code>&nbsp;\u4e2d\u7684\u7b2c\u4e8c\u4e2a\u51fd\u6570\u8c03\u7528\u5b9e\u9645\u4e0a\u8c03\u7528\u7684\u662f&nbsp;<code>A<\/code>&nbsp;\u4e2d\u7684&nbsp;<code>foo() const<\/code>&nbsp;\u51fd\u6570\uff0c\u56e0\u4e3a&nbsp;<code>cbar<\/code>&nbsp;\u8fd4\u56de\u7684\u7c7b\u578b\u662f&nbsp;<code>const A<\/code>\uff0c\u8fd9\u548c&nbsp;<code>A<\/code>&nbsp;\u662f\u4e24\u4e2a\u4e0d\u540c\u7684\u7c7b\u578b\u3002\u8fd9\u5c31\u662f\u4e0a\u9762\u7684\u5f15\u7528\u4e2d\u6700\u540e\u4e00\u53e5\u8bdd\u6240\u8868\u8fbe\u7684\u610f\u601d\u3002\u53e6\u5916\u6ce8\u610f\u5230\uff0c<code>cbar<\/code>&nbsp;\u7684\u8fd4\u56de\u503c\u662f\u4e00\u4e2a\u53f3\u503c\uff0c\u6240\u4ee5\u8fd9\u662f\u4e00\u4e2a\u5b9e\u9645\u7684 CV \u9650\u5b9a\u7684\u53f3\u503c\u7684\u4f8b\u5b50\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"C-11-\u7684\u53f3\u503c\u5f15\u7528\"><a href=\"https:\/\/nettee.github.io\/posts\/2018\/Understanding-lvalues-and-rvalues-in-C-and-C\/#C-11-%E7%9A%84%E5%8F%B3%E5%80%BC%E5%BC%95%E7%94%A8\"><\/a>C++11 \u7684\u53f3\u503c\u5f15\u7528<\/h1>\n\n\n\n<p>C++11 \u6807\u51c6\u4e2d\u5f15\u5165\u7684\u6700\u5f3a\u6709\u529b\u7684\u7279\u6027\u5c31\u662f\u53f3\u503c\u5f15\u7528\uff0c\u4ee5\u53ca\u76f8\u5173\u7684&nbsp;<em>\u79fb\u52a8\u8bed\u4e49 (move semantics)<\/em>&nbsp;\u6982\u5ff5\u3002\u8fd9\u7bc7\u7b80\u77ed\u7684\u6587\u7ae0\u6ca1\u6cd5\u5b8c\u5168\u8ba8\u8bba\u8fd9\u4e2a\u7279\u6027\u3010\u6ce83\uff1a\u641c\u7d22 \u201crvalue references\u201d \u53ef\u4ee5\u627e\u5230\u5f88\u591a\u76f8\u5173\u7684\u8d44\u6599\uff0c\u51e0\u4e2a\u4e2a\u4eba\u8ba4\u4e3a\u6709\u7528\u7684\u8d44\u6599\uff1a<a href=\"http:\/\/www.artima.com\/cppsource\/rvalue.html\" target=\"_blank\" rel=\"noreferrer noopener\">\u8fd9\u4e00\u7bc7<\/a>\uff0c&nbsp;<a href=\"http:\/\/stackoverflow.com\/questions\/5481539\/what-does-t-mean-in-c0x\" target=\"_blank\" rel=\"noreferrer noopener\">\u8fd9\u4e00\u7bc7<\/a>\uff0c\u7279\u522b\u662f&nbsp;<a href=\"http:\/\/thbecker.net\/articles\/rvalue_references\/section_01.html\" target=\"_blank\" rel=\"noreferrer noopener\">\u8fd9\u4e00\u7bc7<\/a>\u3011\uff0c\u4f46\u6211\u60f3\u7ed9\u51fa\u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50\u3002\u5b9e\u9645\u4e0a\uff0c\u5bf9\u5de6\u503c\u548c\u53f3\u503c\u7684\u7406\u89e3\u53ef\u4ee5\u5e2e\u52a9\u6211\u4eec\u7406\u89e3\u4e00\u4e9b\u975e\u5e73\u51e1\u7684\u8bed\u8a00\u6982\u5ff5\u3002<\/p>\n\n\n\n<p>\u8fd9\u7bc7\u6587\u7ae0\u7684\u5927\u90e8\u5206\u5185\u5bb9\u90fd\u5728\u89e3\u91ca\uff1a\u5de6\u503c\u548c\u53f3\u503c\u7684\u4e3b\u8981\u533a\u522b\u662f\uff0c\u5de6\u503c\u53ef\u4ee5\u88ab\u4fee\u6539\uff0c\u800c\u53f3\u503c\u4e0d\u80fd\u3002\u4e0d\u8fc7\uff0cC++11 \u6539\u53d8\u4e86\u8fd9\u4e00\u533a\u522b\u3002\u5728\u4e00\u4e9b\u7279\u6b8a\u7684\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u53f3\u503c\u7684\u5f15\u7528\uff0c\u5e76\u5bf9\u53f3\u503c\u8fdb\u884c\u4fee\u6539\u3002<\/p>\n\n\n\n<p>\u5047\u8bbe\u6211\u4eec\u8981\u5b9e\u73b0\u4e00\u4e2a\u201c\u6574\u6570\u7684 vector\u201d\uff0c\u4e00\u4e9b\u76f8\u5173\u7684\u51fd\u6570\u53ef\u80fd\u662f\u8fd9\u6837\u5b9a\u4e49\u7684\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br>35<br>36<br>37<br>38<br>39<br>40<br>41<br>42<br>43<\/td><td>class Intvec<br>{<br>public:<br>explicit Intvec(size_t num = 0)<br>: m_size(num), m_data(new int[m_size])<br>{<br>log(&#8220;constructor&#8221;);<br>}<br><br>~Intvec()<br>{<br>log(&#8220;destructor&#8221;);<br>if (m_data) {<br>delete[] m_data;<br>m_data = 0;<br>}<br>}<br><br>Intvec(const Intvec&amp; other)<br>: m_size(other.m_size), m_data(new int[m_size])<br>{<br>log(&#8220;copy constructor&#8221;);<br>for (size_t i = 0; i &lt; m_size; ++i)<br>m_data[i] = other.m_data[i];<br>}<br><br>Intvec&amp; operator=(const Intvec&amp; other)<br>{<br>log(&#8220;copy assignment operator&#8221;);<br>Intvec tmp(other);<br>std::swap(m_size, tmp.m_size);<br>std::swap(m_data, tmp.m_data);<br>return *this;<br>}<br>private:<br>void log(const char* msg)<br>{<br>cout &lt;&lt; &#8220;[&#8221; &lt;&lt; this &lt;&lt; &#8220;] &#8221; &lt;&lt; msg &lt;&lt; &#8220;\\n&#8221;;<br>}<br><br>size_t m_size;<br>int* m_data;<br>};<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u8fd9\u6837\uff0c\u6211\u4eec\u5b9a\u4e49\u4e86\u57fa\u672c\u7684\u6784\u9020\u5668\u3001\u6790\u6784\u5668\u3001\u62f7\u8d1d\u6784\u9020\u5668 (copy constructor) \u548c\u62f7\u8d1d\u8d4b\u503c\u64cd\u4f5c\u7b26 (copy assignment operator) \u3010\u6ce84\uff1a\u62f7\u8d1d\u8d4b\u503c\u64cd\u4f5c\u7b26\u7684\u5b9e\u73b0\u662f\u5728\u8003\u8651\u5f02\u5e38\u5b89\u5168\u89d2\u5ea6\u7684\u89c4\u8303\u5199\u6cd5\u3002\u7ed3\u5408\u4f7f\u7528\u62f7\u8d1d\u6784\u9020\u5668\u548c\u4e0d\u4f1a\u629b\u51fa\u5f02\u5e38\u7684<code>std::swap<\/code>\uff0c\u53ef\u4ee5\u4fdd\u8bc1\u5728\u5f02\u5e38\u53d1\u751f\u65f6\u4e0d\u4f1a\u51fa\u73b0\u672a\u521d\u59cb\u5316\u7684\u5185\u5b58\u3011\u3002\u5b83\u4eec\u90fd\u6709\u4e00\u4e2a logging \u51fd\u6570\uff0c\u8ba9\u6211\u4eec\u80fd\u77e5\u9053\u662f\u5426\u8c03\u7528\u4e86\u5b83\u4eec\u3002<\/p>\n\n\n\n<p>\u8fd0\u884c\u4e00\u4e2a\u5c06&nbsp;<code>v1<\/code>&nbsp;\u7684\u5185\u5bb9\u62f7\u8d1d\u5230&nbsp;<code>v2<\/code>&nbsp;\u7684\u4ee3\u7801\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<br>5<br>6<\/td><td>Intvec v1(20);<br>Intvec v2;<br><br>cout &lt;&lt; &#8220;assigning lvalue&#8230;\\n&#8221;;<br>v2 = v1;<br>cout &lt;&lt; &#8220;ended assigning lvalue&#8230;\\n&#8221;;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u8fd0\u884c\u8f93\u51fa\u7684\u7ed3\u679c\u662f\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<br>5<\/td><td>assigning lvalue&#8230;<br>[0x28fef8] copy assignment operator<br>[0x28fec8] copy constructor<br>[0x28fec8] destructor<br>ended assigning lvalue&#8230;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u8fd9\u662f\u6b63\u5e38\u7684\u7ed3\u679c\uff0c\u51c6\u786e\u5c55\u793a\u4e86&nbsp;<code>operator=<\/code>&nbsp;\u7684\u5185\u90e8\u8fc7\u7a0b\u3002\u4f46\u5047\u8bbe\u6211\u4eec\u8981\u5c06\u4e00\u4e2a\u53f3\u503c\u8d4b\u503c\u7ed9&nbsp;<code>v2<\/code>\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<\/td><td>cout &lt;&lt; &#8220;assigning rvalue&#8230;\\n&#8221;;<br>v2 = Intvec(33);<br>cout &lt;&lt; &#8220;ended assigning rvalue&#8230;\\n&#8221;;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u867d\u7136\u8fd9\u91cc\u7684\u4f8b\u5b50\u4e2d\u662f\u8d4b\u503c\u4e00\u4e2a\u65b0\u521b\u5efa\u7684 vector\uff0c\u4f46\u5b83\u53ef\u4ee5\u4ee3\u8868\u66f4\u4e00\u822c\u7684\u60c5\u51b5\u2014\u2014\u521b\u5efa\u4e86\u4e00\u4e2a\u4e34\u65f6\u7684\u53f3\u503c\uff0c\u7136\u540e\u8d4b\u503c\u7ed9&nbsp;<code>v2<\/code>&nbsp;\uff08\u4f8b\u5982\u5f53\u4e00\u4e2a\u51fd\u6570\u8fd4\u56de vector \u7684\u60c5\u51b5\uff09\u3002\u6211\u4eec\u4f1a\u5f97\u5230\u8fd9\u6837\u7684\u8f93\u5165\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<br>5<br>6<br>7<\/td><td>assigning rvalue&#8230;<br>[0x28ff08] constructor<br>[0x28fef8] copy assignment operator<br>[0x28fec8] copy constructor<br>[0x28fec8] destructor<br>[0x28ff08] destructor<br>ended assigning rvalue&#8230;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u8fd9\u770b\u8d77\u6765\u5c31\u8981\u5f88\u591a\u6b65\u9aa4\u4e86\u3002\u7279\u522b\u662f\u8fd9\u91cc\u8c03\u7528\u4e86\u989d\u5916\u7684\u4e00\u5bf9\u6784\u9020\u5668\/\u6790\u6784\u5668\uff0c\u7528\u6765\u521b\u5efa\u548c\u9500\u6bc1\u4e00\u4e2a\u4e34\u65f6\u7684\u5bf9\u8c61\u3002\u7136\u800c\uff0c\u5728\u62f7\u8d1d\u8d4b\u503c\u64cd\u4f5c\u7b26\u4e2d\uff0c\u4e5f\u521b\u5efa\u548c\u9500\u6bc1\u4e86&nbsp;<em>\u53e6\u4e00\u4e2a<\/em>&nbsp;\u4e34\u65f6\u7684\u5bf9\u8c61\u3002\u8fd9\u5b8c\u5168\u662f\u591a\u4f59\u7684\u6ca1\u6709\u610f\u4e49\u7684\u5de5\u4f5c\u3002<\/p>\n\n\n\n<p>\u4e0d\u8fc7\u73b0\u5728\u4f60\u4e0d\u9700\u8981\u591a\u4e00\u4e2a\u4e34\u65f6\u5bf9\u8c61\u4e86\u3002C++11 \u5f15\u5165\u4e86\u53f3\u503c\u5f15\u7528\uff0c\u8ba9\u6211\u4eec\u53ef\u4ee5\u5b9e\u73b0\u201c\u79fb\u52a8\u8bed\u4e49\u201d (move semantics)\uff0c\u7279\u522b\u662f\u53ef\u4ee5\u5b9e\u73b0\u201c\u79fb\u52a8\u8d4b\u503c\u64cd\u4f5c\u7b26\u201d (move assignment operator) \u3010\u6ce85\uff1a\u6587\u7ae0\u4e2d\u4e00\u76f4\u5c06&nbsp;<code>operator=<\/code>&nbsp;\u53eb\u505a \u201c\u62f7\u8d1d\u8d4b\u503c\u64cd\u4f5c\u7b26\u201d (copy assignment operator)\u3002\u5728 C++11 \u4e2d\uff0c\u533a\u5206\u8fd9\u4e24\u4e2a\u6982\u5ff5\u662f\u5f88\u91cd\u8981\u7684\u3011\u3002\u6211\u4eec\u53ef\u4ee5\u4e3a&nbsp;<code>Intvec<\/code>&nbsp;\u52a0\u4e0a\u53e6\u4e00\u4e2a&nbsp;<code>operator=<\/code>\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<br>5<br>6<br>7<\/td><td>Intvec&amp; operator=(Intvec&amp;&amp; other)<br>{<br>log(&#8220;move assignment operator&#8221;);<br>std::swap(m_size, other.m_size);<br>std::swap(m_data, other.m_data);<br>return *this;<br>}<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u7b26\u53f7&nbsp;<code>&amp;&amp;<\/code>&nbsp;\u4ee3\u8868\u4e86\u65b0\u7684&nbsp;<em>\u53f3\u503c\u5f15\u7528 (rvalue reference)<\/em>&nbsp;\u3002\u987e\u540d\u601d\u4e49\uff0c\u53f3\u503c\u5f15\u7528\u53ef\u4ee5\u8ba9\u6211\u4eec\u521b\u5efa\u5bf9\u53f3\u503c\u7684\u5f15\u7528\u3002\u800c\u4e14\u5728\u8c03\u7528\u7ed3\u675f\u540e\uff0c\u53f3\u503c\u5f15\u7528\u5c31\u4f1a\u88ab\u9500\u6bc1\u3002\u6211\u4eec\u53ef\u4ee5\u5229\u7528\u8fd9\u4e2a\u7279\u6027\u5c06\u53f3\u503c\u7684\u5185\u90e8\u5185\u5bb9\u201c\u5077\u201d\u8fc7\u6765\u2014\u2014\u56e0\u4e3a\u6211\u4eec\u4e0d\u518d\u9700\u8981\u4f7f\u7528\u8fd9\u4e2a\u53f3\u503c\u5bf9\u8c61\u4e86\uff01\u8fd9\u6837\u5f97\u5230\u7684\u8f93\u51fa\u662f\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>1<br>2<br>3<br>4<br>5<\/td><td>assigning rvalue&#8230;<br>[0x28ff08] constructor<br>[0x28fef8] move assignment operator<br>[0x28ff08] destructor<br>ended assigning rvalue&#8230;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u7531\u4e8e\u5c06\u4e00\u4e2a\u53f3\u503c\u8d4b\u503c\u7ed9\u4e86&nbsp;<code>v2<\/code>\uff0c\u79fb\u52a8\u8d4b\u503c\u64cd\u4f5c\u7b26\u88ab\u8c03\u7528\u3002\u867d\u7136&nbsp;<code>Intvec(33)<\/code>&nbsp;\u4ecd\u7136\u4f1a\u521b\u5efa\u4e00\u4e2a\u4e34\u65f6\u5bf9\u8c61\uff0c\u8c03\u7528\u5176\u6784\u9020\u5668\u548c\u6790\u6784\u5668\uff0c\u4f46\u8d4b\u503c\u64cd\u4f5c\u7b26\u4e2d\u7684\u53e6\u4e00\u4e2a\u4e34\u65f6\u5bf9\u8c61\u4e0d\u4f1a\u518d\u521b\u5efa\u4e86\u3002\u8fd9\u4e2a\u8d4b\u503c\u64cd\u4f5c\u7b26\u76f4\u63a5\u5c06\u53f3\u503c\u7684\u5185\u90e8\u5185\u5bb9\u548c\u81ea\u5df1\u7684\u76f8\u4ea4\u6362\uff0c\u81ea\u5df1\u83b7\u5f97\u53f3\u503c\u7684\u5185\u5bb9\uff0c\u7136\u540e\u53f3\u503c\u7684\u6790\u6784\u5668\u4f1a\u9500\u6bc1\u81ea\u5df1\u539f\u5148\u7684\u5185\u5bb9\uff0c\u800c\u8fd9\u4e00\u5185\u5bb9\u5df2\u7ecf\u4e0d\u9700\u8981\u4e86\u3002\u4f18\u96c5\u3002<\/p>\n\n\n\n<p>\u518d\u63d0\u9192\u4e00\u904d\uff0c\u8fd9\u4e2a\u4f8b\u5b50\u53ea\u5c55\u793a\u4e86\u79fb\u52a8\u8bed\u4e49\u548c\u53f3\u503c\u5f15\u7528\u7684\u51b0\u5c71\u4e00\u89d2\u3002\u4f60\u53ef\u4ee5\u731c\u5230\uff0c\u8fd9\u5b9e\u9645\u4e0a\u662f\u4e00\u4e2a\u590d\u6742\u7684\u8bdd\u9898\uff0c\u8981\u8003\u8651\u5f88\u591a\u7279\u6b8a\u60c5\u51b5\u548c\u9677\u9631\u3002\u6211\u662f\u60f3\u5c55\u793a\u4e00\u4e2a C++ \u4e2d\u5de6\u503c\u53f3\u503c\u533a\u522b\u7684\u4e00\u4e2a\u5f88\u6709\u8da3\u7684\u5e94\u7528\u3002\u7f16\u8bd1\u5668\u663e\u7136\u77e5\u9053\u54ea\u91cc\u662f\u4e2a\u53f3\u503c\uff0c\u4f1a\u5728\u7f16\u8bd1\u65f6\u9009\u62e9\u8c03\u7528\u5408\u9002\u7684\u6784\u9020\u5668\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"\u603b\u7ed3\"><a href=\"https:\/\/nettee.github.io\/posts\/2018\/Understanding-lvalues-and-rvalues-in-C-and-C\/#%E6%80%BB%E7%BB%93\"><\/a>\u603b\u7ed3<\/h1>\n\n\n\n<p>\u5373\u4f7f\u4e0d\u8003\u8651\u5de6\u503c\u548c\u53f3\u503c\u7684\u95ee\u9898\uff0c\u4f60\u4e5f\u53ef\u4ee5\u5199\u5f88\u591a C++ \u4ee3\u7801\uff0c\u7136\u540e\u628a\u8fd9\u4e9b\u95ee\u9898\u770b\u4f5c\u7f16\u8bd1\u5668\u67d0\u4e9b\u9519\u8bef\u8b66\u544a\u4e2d\u5947\u602a\u7684\u884c\u8bdd\u3002\u7136\u800c\uff0c\u8fd9\u7bc7\u6587\u7ae0\u60f3\u8868\u660e\uff0c\u5bf9\u8fd9\u4e2a\u95ee\u9898\u6709\u4e00\u4e9b\u9886\u609f\u7684\u8bdd\uff0c\u4f1a\u4f7f\u4f60\u80fd\u66f4\u6df1\u5165\u5730\u7406\u89e3\u4e00\u4e9b C++ \u4ee3\u7801\uff0c\u4e5f\u66f4\u80fd\u5f04\u61c2\u4e00\u4e9b C++ \u89c4\u8303\u548c\u8bed\u8a00\u4e13\u5bb6\u7684\u8ba8\u8bba\u3002<\/p>\n\n\n\n<p>\u53e6\u5916\uff0c\u5728\u65b0\u7684 C++ \u89c4\u8303\u4e2d\uff0c\u56e0\u4e3a C++11 \u5f15\u5165\u4e86\u53f3\u503c\u5f15\u7528\u548c\u79fb\u52a8\u8bed\u4e49\uff0c\u8fd9\u4e2a\u8bdd\u9898\u53d8\u5f97\u66f4\u91cd\u8981\u4e86\u3002\u8981\u60f3\u771f\u6b63\u7406\u89e3\u8fd9\u4e2a\u8bed\u8a00\u7684\u4e00\u4e9b\u65b0\u7279\u6027\uff0c\u900f\u5f7b\u5730\u7406\u89e3\u5de6\u503c\u548c\u53f3\u503c\u5c31\u53d8\u5f97\u91cd\u8981\u4e86<\/p>\n","protected":false},"excerpt":{"rendered":"<p>https:\/\/eli.thegreenplace.net\/2011\/12\/15\/understanding- [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/5896"}],"collection":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5896"}],"version-history":[{"count":4,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/5896\/revisions"}],"predecessor-version":[{"id":5901,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=\/wp\/v2\/posts\/5896\/revisions\/5901"}],"wp:attachment":[{"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5896"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5896"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.coolcoding.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5896"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}