LoginSignup
6
6

More than 5 years have passed since last update.

僕は非nullなスマートポインターがほしいと思ったんだ

Last updated at Posted at 2015-09-12

前略姉さんヌルポが怖いですめんどいです不要です

ヌルポインターは怖い。いまさら言うまでもなく、怖い
だがヌルポチェックは面倒くさい。よく忘れるし、よくさぼる

だがしかし
冷静に考えてみればnewはnullを返さない
無効値ならばoptionalのように明示的に無効値を表明したほうがスマートだ
本当の本当にnullptrが必要な場面というのはそうそう多くないはずだ

だから僕は非nullなスマートポインターがほしいと思ったんだ

なおここでスマートポインターとは

  • share_ptr
  • unique_ptr

の2種を指す

コンストラクタはどうあるべきか

nullptrを引数にとれるコンストラクタやデフォルトコンストラクタをすべて潰し、生成にはmake_shared , make_uniqueなどを用いる

  • 内部状態がnullになってはならないので当然nullptrを引数にとるコンストラクタはあるべきではない
  • デフォルトコンストラクタについてはTがデフォルトコンストラクタを持っているのならばnew T()してもよいのだが、デフォルトでnewするのはコストが大きく余計なお世話な感じがあるので潰してしまうべきだ

moveはどうするべきか

moveされたオブジェクト(つまり普段はnullになっていた右辺値のほう)はどうあるべきか

moveせずコピーする?

a=std::move(b);  //a=b;と等価

shared_ptrの場合計算コストが増えてしまうが、まあ良いだろう
unique_ptrの場合そもそもコピーが使えない

フラグを保持しておき、所有権の有無を表す?

a=std::move(b);  //b==(ptr=p,flag=false)

nullableな普通のスマートポインタの劣化に過ぎないし、使うか分からないフラグを持ち続けるのはなかなかにばかばかしい

気にせずnullをぶち込め!!

a=std::move(b);  //b==nullptr ??

非nullポインターにnullをぶち込む非常識極まりない畜生行為。人間の所業と思えない

だがしかし、「move後のbの挙動については合法な範囲内でどのような状態になってもよい」とされている

つまり、非ヌルスマポが「この状態はnullptrだが特例的に合法」であると言い張れば何も問題ないのではなかろうか

例えば一般のunique_ptrはmove後nullptrかそれとも元の値を保持しているかは、「ご自由に」である
ご自由に、だとどうなっているのかさっぱりわからないので再代入されるまで触るべきでない
bは再代入されるまで触るべきではない値だったのだ

どうせ再代入で書き換えられるのでnullでも使う上で問題ないのでは?
しかもこの行動はもともとのスマートポインターと同じ速さで動く

結論としては

非nullptrが超限定的にnullになる可能性を受け入れれば、非nullスマートポインターが完成する。という大変後味の悪い話となった

正直move後の値を触る奴のプロダクトなんて知らん、という感じはするのだが
そのバカをやるのは締切直前の自分だったりするので
コピーコンストラクタとoperator=にassertで事前チェックを仕込むぐらいのやさしさはあってもいいかもしれない

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6