teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

4

逆参照は間接参照とも…

2019/09/15 15:06

投稿

raccy
raccy

スコア21767

answer CHANGED
@@ -1,5 +1,7 @@
1
- いいえ、[ヌルポインタの逆参照](https://ja.cppreference.com/w/cpp/language/ub#.E3.83.8C.E3.83.AB.E3.83.9D.E3.82.A4.E3.83.B3.E3.82.BF.E3.81.AE.E9.80.86.E5.8F.82.E7.85.A7)は未定義動作になるため、該当の部分の前でチェックしておく必要があります。二つの違いは「だれが`nullptr`の場合を担保するのか?」です。
1
+ いいえ、[ヌルポインタの逆参照(間接参照)](https://ja.cppreference.com/w/cpp/language/ub#.E3.83.8C.E3.83.AB.E3.83.9D.E3.82.A4.E3.83.B3.E3.82.BF.E3.81.AE.E9.80.86.E5.8F.82.E7.85.A7)は未定義動作になるため、該当の部分の前でチェックしておく必要があります。二つの違いは「だれが`nullptr`の場合を担保するのか?」です。
2
2
 
3
+ ※ 逆参照"dereference"(間接参照"indirection"とも呼ばれる)と参照渡しにおける左辺値参照"lvalue reference"は全く別の概念であり、混合してはいけません。
4
+
3
5
  ### ポインタの値渡しの場合
4
6
 
5
7
  関数側が`nullptr`が来ることを想定しておかなければなりません。`nullptr`が渡された場合どのような動作をするのか、例えば、
@@ -17,7 +19,7 @@
17
19
 
18
20
  関数側は`nullptr`が来ることを想定する必要がありません。必ず何かしらの実体が引数と渡されます。ですので、ポインタの値渡しであったような、`nullptr`であったらの動作を定義する必要も無いですし、チェックする必要もありません。
19
21
 
20
- さて、呼び出し側はどうかと言うことです。呼び出し側もチェックする必要は無いように思います。しかし、もともとポインタであった物を渡したい場合、逆参照して通常のオブジェクトとして渡す必要があります。質問のコードの`*pRet`の部分ですね。ポインタを逆参照するとき、そのポインタが`nullptr`ではないことを保証するのは、逆参照を書いている側です。つまり、呼び出し側で`*pRet`が安全に使えるかを確認しておく必要があります。結局の所、コード全体ではどこかでチェックは必要になると言うことです。
22
+ さて、呼び出し側はどうかと言うことです。呼び出し側もチェックする必要は無いように思います。しかし、もともとポインタであった物を渡したい場合、逆参照して通常のオブジェクトとして渡す必要があります。質問のコードの`*pRet`の部分ですね。ポインタを逆参照(間接参照)するとき、そのポインタが`nullptr`ではないことを保証するのは、逆参照(間接参照)を書いている側です。つまり、呼び出し側で`*pRet`が安全に使えるかを確認しておく必要があります。結局の所、コード全体ではどこかでチェックは必要になると言うことです。
21
23
 
22
24
  ---
23
25
 

3

文が変だった

2019/09/15 15:06

投稿

raccy
raccy

スコア21767

answer CHANGED
@@ -1,4 +1,4 @@
1
- いいえ、[ヌルポインタの逆参照](https://ja.cppreference.com/w/cpp/language/ub#.E3.83.8C.E3.83.AB.E3.83.9D.E3.82.A4.E3.83.B3.E3.82.BF.E3.81.AE.E9.80.86.E5.8F.82.E7.85.A7)は未定義動作になるため、該当の部分の前でチェックしておく必要す。二つの違いは「だれが`nullptr`の場合を担保するのか?」です。
1
+ いいえ、[ヌルポインタの逆参照](https://ja.cppreference.com/w/cpp/language/ub#.E3.83.8C.E3.83.AB.E3.83.9D.E3.82.A4.E3.83.B3.E3.82.BF.E3.81.AE.E9.80.86.E5.8F.82.E7.85.A7)は未定義動作になるため、該当の部分の前でチェックしておく必要があります。二つの違いは「だれが`nullptr`の場合を担保するのか?」です。
2
2
 
3
3
  ### ポインタの値渡しの場合
4
4
 

2

感じにする

2019/09/15 06:19

投稿

raccy
raccy

スコア21767

answer CHANGED
@@ -9,7 +9,7 @@
9
9
  3. 未定義動作。(C由来の関数のほとんどがそう)
10
10
  4. 例外を発生させる。(C++では処理が重い例外は敬遠されるせいか、あまり見かけないような気がする。Javaではこちらが多い印象(勝手にヌルポになっているというのもあるが))
11
11
 
12
- 等が考えられ、あらかじめ決めておきます。そして、3.の未定義動作を除けば、関数ないで`nullptr`であるかをチェックして、あらかじめ決めておいた動作をする必要があるでしょう。
12
+ 等が考えられ、あらかじめ決めておきます。そして、3.の未定義動作を除けば、関数で`nullptr`であるかをチェックして、あらかじめ決めておいた動作をする必要があるでしょう。
13
13
 
14
14
  対して、呼び出し側は`nullptr`を渡しても、`nullptr`の時の動作をするだけなので、その動作で十分であれば、チェックしておく必要がありません。`if (p != nullptr) free(p);`とかしなくても良いって事です。
15
15
 

1

誤字の修正

2019/09/15 02:22

投稿

raccy
raccy

スコア21767

answer CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ### ポインタの値渡しの場合
4
4
 
5
- 関数側が`nullptr`が来ることを想定しておかなければなりません。`nullptr`が渡された場合どのようなどうさするのか、例えば、
5
+ 関数側が`nullptr`が来ることを想定しておかなければなりません。`nullptr`が渡された場合どのような動作をするのか、例えば、
6
6
 
7
7
  1. 何もしない。(`free()`がそう)
8
8
  2. 必要なサイズを返す、必要な領域が確保されて返す、など別の動作をする。(Win32APIに多い)