ゆとりーなの日記

日記的な事を書いて行くと思はれる

オワタ四連刻一向聴

当初の予想通りでした。大損害です。四連刻一向聴完成です。
そういえば天鳳で初段になりました。大体125戦目位です。ちょっと遅めですかね。しかし世紀末麻雀は天鳳でも或る程度は通用するらしいです。

演算子オーバーロード特集

昨日何も書かなかったんで特集第5弾行きます。もうやけくそですね。

演算子オーバーロードって害悪だよね

良く聞きます。こんな機能いらんという意見ですね。この手の意見を言う人にはGCまだ〜?っていう人が多い気がします。で、演算子オーバーロードとは演算子の挙動を自分で定義できる素敵な機能です。好きなように定義できるのでとんでも実装な+演算子とかが作れるんですね。例えばプログラムを落とす+演算子とかも余裕で作れます。害悪派はこんなこと出来ても出来なくてもいいし、変なことされる危険のある機能は要らないというのも頷けますね。因みに沸き立つCプラー名古屋313は演算子オーバーロード大好きです。

オーバーロード出来ない演算子があるって聞いたけど?

ありますね。こればかりは決まりなのでどうしようもありません。オーバーロード出来ない子達は、

(追記:キャスト演算子を忘れてました。)
(更に追記:reinterpret_cast以外は0x以降オーバロード可能らしいです。)

  • static_cast
  • reinterpret_cast
  • const_cast
  • dynamic_cast

(追記:newとoperator newをきちんと区別する派閥もあるようです。)

  • new
  • delete
  • new[]
  • delete[]

ですね。括弧内は適当に付けた名前です。
グローバル空間になると突如オーバーロード出来なくなる子達もいます。staticメンバ関数でも駄目です。
(追記:*を忘れてました。あと0x以降はオーバーロード可能らしいです。)

そういえば組み込み型しか出てこない演算子オーバーロードも確か駄目だった気がします。

オーバーロード禁止が叫ばれる演算子の噂を聞いたけど?

多分、

のことですね。この子達の組み込み型の時の挙動を見ると、&&演算子で言えば、左辺が偽を返した瞬間右辺は評価されないことが確定します。関数呼び出しでは、引数の評価順がコンパイラの気まぐれなため、この子達は組み込み型と同じ挙動を再現することが出来ないんです。メンバ関数にしても解決することはありません。因ってオーバーロードすべきでないとされます。条件系がやりたいなら、取り敢えず==演算子、!=演算子、!演算子とvoid*キャスト演算子オーバーロードしておけば良いんじゃないんですかね。因みにBoost先生クラスになると、平然と&&とかをオーバーロードしてきます。3値ブールとかです。

オーバーロードが避けられる演算子を見たけど?

しいて言えば、

  • ++(インクリメント)
  • --(デクリメント)
  • +,-,*,/(プラス演算子とその仲間たち)

ですかね。++系が嫌われるのは、ジャンルによっては人によって++の挙動の予想が異なることが挙げれれます。例をあげると、ディレクトリを管理するクラスとかですかね。++が階層を下がるのか、上るのか、どっちもありな気もしますね。
次いで四則演算演算子ですが、これは組み込み型の挙動をまねるとコピーが必要になるからですね。クラスのコピーは重いので避けたいという人はまずこの手の演算子オーバーロードしません。TMPというコピーを避けるためのテンプレートバリバリの技法があることにはありますが。

組み込み型の再現ってそんなに大事かい?

組み込み型の場合の演算子の挙動を再現するために、オーバーロードが出来なかったり、コピーが発生して遅くなったりするなら、その部分を再現しなければいいじゃないかという意見は流石にないでしょう。組み込み型と同じという方針を守っていれば、演算子の挙動を良く知れ渡った組み込み型の時に例えて考えられるわけです。例えば+演算子で、コピーが嫌だからと言って引数をそのまま参照で返したら、元の値がいつの間にか変わってしまうことがあり得ます。こんなことが実際に起こったらびっくりです。原因を探すのも大変だと思いますよ。こんなこと普通+演算子では起こらないという固定観念がありますからね。

組み込み型の再現を徹底するとこうなるけど?

添え字演算子の事です。添え演算子はアクセス範囲が境界を超えていた場合の挙動は動作未定義となります。よくあるクラスの添え字演算子オーバーロードの例では、アクセス範囲の境界を超えているかを検査して、超えていたら適切に対処すると言ったものがあります。ところがこれをやると組み込み型の時と挙動が変わりますね。より安全にするんだから良いという人もいるかもしれませんが、私は添え字演算子オーバーロードするときは、アクセス範囲が境界を超えていた場合の挙動は動作未定義をそのまま守ります。組み込み型の再現の徹底です。アクセス範囲調べたいときは専用のメソッドを用意しますね。std::vector等もこの方針に従ってか、添え字演算子の時はアクセス範囲越え時の動作は未定義、at()メソッドでは例外を投げるという仕様になっていますしね。そもそも添え字演算子は内部メンバの参照を返すことが殆どだから、こんなとこで安全性を高めてもしょうがないと思います。参照返しによる危険性はどうあがいても避けられませんからね。
第5回もおしまいです。