Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 41b88c8

Browse files
book: redo string literal explanation (#237)
1 parent 25a8fd2 commit 41b88c8

File tree

2 files changed

+40
-18
lines changed

2 files changed

+40
-18
lines changed

‎book/en-us/03-runtime.md‎

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -263,22 +263,34 @@ Temporary variables returned by non-references, temporary variables generated
263263
by operation expressions, original literals, and Lambda expressions
264264
are all pure rvalue values.
265265
266-
Note that a string literal became rvalue in a class, and remains an lvalue in other cases (e.g., in a function):
266+
Note that a literal (except a string literal) is a prvalue. However, a string
267+
literal is an lvalue with type `const char` array. Consider the following examples:
267268
268269
```cpp
269-
class Foo {
270-
const char*&& right = "this is a rvalue";
271-
public:
272-
void bar() {
273-
right = "still rvalue"; // the string literal is a rvalue
274-
}
275-
};
270+
#include <type_traits>
276271
277272
int main() {
278-
const char* const &left = "this is an lvalue"; // the string literal is an lvalue
273+
// Correct. The type of "01234" is const char [6], so it is an lvalue
274+
const char (&left)[6] = "01234";
275+
276+
// Assert success. It is a const char [6] indeed. Note that decltype(expr)
277+
// yields lvalue reference if expr is an lvalue and neither an unparenthesized
278+
// id-expression nor an unparenthesized class member access expression.
279+
static_assert(std::is_same<decltype("01234"), const char(&)[6]>::value, "");
280+
281+
// Error. "01234" is an lvalue, which cannot be referenced by an rvalue reference
282+
// const char (&&right)[6] = "01234";
279283
}
280284
```
281285

286+
However, an array can be implicitly converted to a corresponding pointer.The result, if not an lvalue reference, is an rvalue (xvalue if the result is an rvalue reference, prvalue otherwise):
287+
288+
```cpp
289+
const char* p = "01234"; // Correct. "01234" is implicitly converted to const char*
290+
const char*&& pr = "01234"; // Correct. "01234" is implicitly converted to const char*, which is a prvalue.
291+
// const char*& pl = "01234"; // Error. There is no type const char* lvalue
292+
```
293+
282294
**xvalue, expiring value** is the concept proposed by C++11 to introduce
283295
rvalue references (so in traditional C++, pure rvalue and rvalue are the same concepts),
284296
a value that is destroyed but can be moved.

‎book/zh-cn/03-runtime.md‎

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -224,22 +224,32 @@ int main() {
224224
要么是求值结果相当于字面量或匿名临时对象,例如 `1+2`。非引用返回的临时变量、运算表达式产生的临时变量、
225225
原始字面量、Lambda 表达式都属于纯右值。
226226

227-
需要注意的是,字符串字面量只有在类中才是右值,当其位于普通函数中是左值。例如:
227+
需要注意的是,字面量除了字符串字面量以外,均为纯右值。而字符串字面量是一个左值,类型为 `const char` 数组。例如:
228228

229229
```cpp
230-
class Foo {
231-
const char*&& right = "this is a rvalue"; // 此处字符串字面量为右值
232-
public:
233-
void bar() {
234-
right = "still rvalue"; // 此处字符串字面量为右值
235-
}
236-
};
230+
#include <type_traits>
237231

238232
int main() {
239-
const char* const &left = "this is an lvalue"; // 此处字符串字面量为左值
233+
// 正确,"01234" 类型为 const char [6],因此是左值
234+
const char (&left)[6] = "01234";
235+
236+
// 断言正确,确实是 const char [6] 类型,注意 decltype(expr) 在 expr 是左值
237+
// 且非无括号包裹的 id 表达式与类成员表达式时,会返回左值引用
238+
static_assert(std::is_same<decltype("01234"), const char(&)[6]>::value, "");
239+
240+
// 错误,"01234" 是左值,不可被右值引用
241+
// const char (&&right)[6] = "01234";
240242
}
241243
```
242244

245+
但是注意,数组可以被隐式转换成相对应的指针类型,而转换表达式的结果(如果不是左值引用)则一定是个右值(右值引用为将亡值,否则为纯右值)。例如:
246+
247+
```cpp
248+
const char* p = "01234"; // 正确,"01234" 被隐式转换为 const char*
249+
const char*&& pr = "01234"; // 正确,"01234" 被隐式转换为 const char*,该转换的结果是纯右值
250+
// const char*& pl = "01234"; // 错误,此处不存在 const char* 类型的左值
251+
```
252+
243253
**将亡值(xvalue, expiring value)**,是 C++11 为了引入右值引用而提出的概念(因此在传统 C++ 中,
244254
纯右值和右值是同一个概念),也就是即将被销毁、却能够被移动的值。
245255

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /