Skip to content

Commit c5f0cb7

Browse files
author
mikeblome
committed
guaranteed copy elision v1
1 parent 8b2d1f1 commit c5f0cb7

3 files changed

Lines changed: 50 additions & 20 deletions

File tree

docs/cpp/functions-cpp.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ int main()
379379
}
380380
```
381381

382-
4. Although not "returning values" in the strict sense, you can also define any number of parameters to use pass-by reference so that the function can modify the value of the object that the caller provides.
382+
4. Although not "returning values" in the strict sense, you can define any number of parameters to use pass-by reference so that the function can modify or initialize the values of objects that the caller provides. For more information, see [Reference-Type Function Arguments](reference-type-function-arguments.md).
383383

384384
## Function pointers
385385
C++ supports function pointers in the same manner as the C language. However a more type-safe alternative is usually to use a function object.

docs/cpp/if-else-statement-cpp.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ Controls conditional branching.
4545
## Syntax
4646

4747
```
48-
49-
if ( expression )
48+
if ( expression )
5049
   statement1
5150
[else
5251
   statement2]

docs/cpp/lvalues-and-rvalues-visual-cpp.md

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: "Lvalues and Rvalues (Visual C++) | Microsoft Docs"
2+
title: "Value Categories: Lvalues and Rvalues (Visual C++) | Microsoft Docs"
33
ms.custom: ""
44
ms.date: "11/04/2016"
55
ms.reviewer: ""
@@ -34,22 +34,18 @@ translation.priority.ht:
3434
- "zh-tw"
3535
---
3636
# Lvalues and Rvalues (Visual C++)
37-
Every C++ expression is either an lvalue or an rvalue. An lvalue refers to an object that persists beyond a single expression. You can think of an lvalue as an object that has a name. All variables, including nonmodifiable (`const`) variables, are lvalues. An rvalue is a temporary value that does not persist beyond the expression that uses it. To better understand the difference between lvalues and rvalues, consider the following example:
38-
39-
```
40-
// lvalues_and_rvalues1.cpp
41-
// compile with: /EHsc
42-
#include <iostream>
43-
using namespace std;
44-
int main()
45-
{
46-
int x = 3 + 4;
47-
cout << x << endl;
48-
}
49-
```
50-
51-
In this example, `x` is an lvalue because it persists beyond the expression that defines it. The expression `3 + 4` is an rvalue because it evaluates to a temporary value that does not persist beyond the expression that defines it.
52-
37+
Every C++ expression has a type, and belongs to a *value category*. The value categories are the basis for rules that compilers must follow when creating, copying, and moving temporary objects during expression evaluation. In C++17 the rules were restated to ensure that all compilers behave identically by not creating objects unless they are actually required. The new specified behavior is called "guaranteed copy elision." It helps to make your code more portable and efficient and eliminates the need to provide copy and move constructors for types that never use them.
38+
39+
The C++17 standard defines value categories as follows:
40+
41+
- A *glvalue* is an expression whose evaluation determines the identity of an object, bit-field, or function.
42+
- A *prvalue* is an expression whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears.
43+
- An *xvalue* is a glvalue that denotes an object or bit-field whose resources can be reused (usually because it is near the end of its lifetime). [ Example: Certain kinds of expressions involving rvalue references (8.3.2) yield xvalues, such as a call to a function whose return type is an rvalue reference or a cast to an rvalue reference type. ]
44+
- An *lvalue* is a glvalue that is not an xvalue.
45+
- An *rvalue* is a prvalue or an xvalue.
46+
47+
Examples of lvalues include variables, including `const` variables, array elements, bit-fields, unions, and class members. Examples of rvalues include literals, function calls, and temporary objects that are created during expression evalution but accessible only by the compiler.
48+
5349
The following example demonstrates several correct and incorrect usages of lvalues and rvalues:
5450

5551
```
@@ -79,6 +75,41 @@ int main()
7975

8076
> [!NOTE]
8177
> The examples in this topic illustrate correct and incorrect usage when operators are not overloaded. By overloading operators, you can make an expression such as `j * 4` an lvalue.
78+
79+
The following example shows the new behavior for guaranteed copy elision. Note that construction from temporary objects succeeds in both cases despite the absence of a move constructor.
80+
81+
```cpp
82+
#include <iostream>
83+
#include <string>
84+
85+
using namespace std;
86+
87+
struct S {
88+
S(int) { cout << "S(int)" << endl; }
89+
S(S&) = delete;
90+
S(S&&) = delete; // { cout << "move" << endl; }
91+
///...
92+
};
93+
94+
S make_s()
95+
{
96+
// Return value initialized directly at call site.
97+
// In Visual Studio 2015 this does not compile due to deleted move ctor.
98+
return S(42);
99+
}
100+
101+
102+
int main()
103+
{
104+
auto nm = make_s();
105+
S x4 = 5; // Construct from an rvalue.
106+
}
107+
```
108+
The program produces this output:
109+
```output
110+
S(int)
111+
S(int)
112+
```
82113

83114
The terms *lvalue* and *rvalue* are often used when you refer to object references. For more information about references, see [Lvalue Reference Declarator: &](../cpp/lvalue-reference-declarator-amp.md) and [Rvalue Reference Declarator: &&](../cpp/rvalue-reference-declarator-amp-amp.md).
84115

0 commit comments

Comments
 (0)