2014/9/20 Cryolite 
Boost.勉強会#16 大阪 
1 
左と右の話
2 
左と右の区別は大事です 
※画像はイメージです
3 
左辺値・右辺値とは何か? 
i = 42; 
左辺値右辺値 
式の値を格納した場所 
Cf. “Location value” 
式の値
i 
int &f(); f() 全て規格に 
4 
左辺値・右辺値とは 
全ての式がおのおの持つ属性 
左辺値となる式 
右辺値となる式 
42, i + j 
int g(); g() 
MyClass(arg) 
書いてある
5 
代入演算子における 
左辺値・右辺値の例 
i = 42; 
変数“i” からなる式 
“i” の値を格納した場所(左辺値)
6 
代入演算子における 
左辺値・右辺値の例 
i = 42; 
リテラル“42” からなる式 
“42” の値(右辺値)
7 
代入演算子における 
左辺値・右辺値の例 
i = 42; 
“i” という式の値を格納した場所 
(左辺値)に, “42” という式の値 
(右辺値)を代入する
8 
代入演算子における 
左辺値・右辺値の例 
i = 42; 
“i = 42” という式の値を 
格納した場所(左辺値)
9 
代入演算子の右辺に 
左辺値が来たらどうなるの? 
j = i 
“j” という式の値を格納した場所 
(左辺値)に, “i” という式の値を 
格納した場所(左辺値)を代入する?
10 
代入演算子の右辺に 
左辺値が来たらどうなるの? 
j = i 
“j” という式の値を格納した場所 
(左辺値)に, “i” という式の値を 
格納した場所(左辺値)を代入する?
11 
代入演算子は 
右辺に右辺値が欲しい! 
= 
右辺には右辺値が欲しい 
左辺には左辺値が欲しい
12 
代入演算子は 
右辺に右辺値が欲しい! 
左辺に期待通り左辺値が来た!問題無し! 
j =
13 
代入演算子は 
右辺に右辺値が欲しい! 
右辺に右辺値が欲しいのに左辺値が来た! 
欲しいのと違う! 
j = i
14 
代入演算子は 
右辺に右辺値が欲しい! 
右辺に右辺値が欲しいのに左辺値が来た! 
欲しいのと違う! 
j = i 
左辺値を右辺値として解釈しなおそう! 
j = i
左辺値から 
右辺値への変換 
lvalue-to-rvalue 
15 
代入演算子は 
右辺に右辺値が欲しい! 
右辺に右辺値が欲しいのに左辺値が来た! 
欲しいのと違う! 
j = i 
左辺値を右辺値として解釈しなおそう! 
j = i 
conversion
値が格納された場所(左辺値) 
から値(右辺値)を取り出す 
左辺値から 
右辺値への変換 
lvalue-to-rvalue 
16 
代入演算子は 
右辺に右辺値が欲しい! 
右辺に右辺値が欲しいのに左辺値が来た! 
欲しいのと違う! 
j = i 
左辺値を右辺値として解釈しなおそう! 
j = i 
conversion
“j” という式の値を格納した場所 
(左辺値)に, “i” という式の値 
(右辺値)を代入する 
左辺値から 
右辺値への変換 
lvalue-to-rvalue 
17 
代入演算子は 
右辺に右辺値が欲しい! 
j = i 
j = i 
conversion
他の組み込み演算子, statement 
等は左右どちらが欲しい? 
R + R -R &L L = R 
int i = R; 
全て規格に 
int &ri = L; 
書いてある 
if (R) {… 
18
ある式が,出現する文脈で左辺値・右辺値の 
19 
式の左辺値・右辺値に 
関する2つの視点 
式自身が左辺値なのか右辺値なのか 
i 42 
どちらであることを要求されるのか 
左辺値が欲しい= 
右辺値が欲しい
20 
式の左辺値・右辺値に関する 
2つの視点とL-to-R 変換 
ある式が左辺値 
である 
右辺値 
である 
出現して 
いる文脈 
で 
左辺値である 
ことが要求さ 
れている 
そのま 
まで 
O.K. 
コンパ 
イルエ 
ラー 
右辺値である 
ことが要求さ 
れている 
L-to-R 
変換が 
起きる 
そのま 
まで 
O.K.
21 
式の左辺値・右辺値に関する 
2つの視点とL-to-R 変換 
ある式が左辺値 
である 
右辺値 
である 
出現して 
いる文脈 
で 
左辺値である 
ことが要求さ 
れている 
そのま 
まで 
O.K. 
コンパ 
イルエ 
ラー 
右辺値である 
ことが要求さ 
れている 
L-to-R 
変換が 
起きる 
そのま 
まで 
O.K. 
&42 
42=0
22 
全ては規格のシナリオ通りに 
• 式自身が左辺値か右辺値か 
⇒全て規格に書いてある 
• 個々の文脈で式に左辺値・ 
右辺値のどちらが要求されるか 
⇒全て規格に書いてある 
• いつ左辺値から右辺値への 
変換が起きるか 
⇒全て上2つから判断できる
左辺値から右辺値への変換が 
起きる場所は全て規格に書いてある 
23
全てのコーナーケースは 
左辺値から右辺値への変換に通ず 
24
全てのコーナーケースは 
左辺値から右辺値への変換に通ず 
25
例:オブジェクトが未構築な 
領域にどんな操作が許されるか? 
26 
オブジェクトに対して左辺値から 
右辺値への変換が起きたらアウト 
void *p = std::malloc(sizeof(int 
int &ri = *p; 
セーフ 
&ri; 
ri + 1; 
アウト 
int *pi = new (p) int(42);
27 
例:未初期化な変数に 
どんな操作が許されるか? 
変数に対して左辺値から右辺値への 
変換が起きないようにすればセーフ 
void f(int &); 
void g(int); 
int i; 
f(i); 
セーフ 
g(i);アウト
28 
例:型の完全な定義が 
いつ必要になるか? 
左辺値から右辺値への変換が起きた 
オブジェクトの型は完全でなければならない 
class X; 
void f(X &x) { 
セーフ 
&x; 
static_cast<X>(x); 
} アウト
29 
例:変数の定義がいつ必要に 
なる(odr-usedされる)か? 
変数がコード中に出現すればodr-used 
ただし,変数がconstant expression であり 
即座にL-to-R 変換が起きる場合は対象外 
Template<typename T> 
struct X { 
static constexpr int i = 42; 
}; 
int j = i + 1; 
int *p = &i; 
アウト 
セーフ
xvalue, prvalue, 
glvalue の話はどこに行った? 
現在のC++ の左辺値・右辺値の 
区別は実は3種類 
• lvalue 
• xvalue 
• prvalue
xvalue, prvalue, 
glvalue の話はどこに行った? 
“Location” の 
意味を持つか 
寿命が短い 
lvaue Yes No 
xvalue Yes Yes 
prvalue No Yes
xvalue, prvalue, 
glvalue の話はどこに行った? 
“Location” の 
意味を持つか 
寿命が短い 
lvaue Yes No 
xvalue Yes Yes 
prvalue No Yes 
今日の発表の 
左と右の境界
xvalue, prvalue, 
glvalue の話はどこに行った? 
“Location” の 
意味を持つか 
寿命が短い 
lvaue Yes No 
xvalue Yes Yes 
prvalue No Yes 
move semantics, 右辺値参照で 
重要な左と右の境界
まとめ: 
• 左辺値とは何か,右辺値とは何か 
• 左辺値から右辺値への変換とは何か,それは 
いつ起きるのか 
• 左辺値から右辺値への変換がいつ起きるのか 
は様々なコーナーケースでの判断に重要 
• 左辺値と右辺値の区別はmove semantics, 
右辺値参照の話でも重要だが,本発表での左 
辺値と右辺値の区別の場合と境界線が異なる 
34

左と右の話