アカウント名:
パスワード:
`key_data_->label().empty()`に副作用がないなら条件付きか否かで変わらなくない?と思ったが、C++だと&はビット演算で両方trueでもfalseになることがあるのか。&&と&は条件付きかだけじゃなく評価の仕方が違うのね。C#で両辺boolなら無視できるパフォーマンス上の問題でしかないからピンとこなかったわ。
C#とかJavaでも両辺が整数とかだったりすると…C#とかJavaだと評価の仕方が違うというかboolとそれ以外で事実上全然別の演算子ですね。
C#は演算子オーバーロードがあるのでなんでもあり。ただifの条件にbool以外は入らないからこういう問題はまず起こらない。boolへの暗黙の型変換が定義されてれば起こせなくはないがまぁ起きない
判定結果をブール値として変数に入れようとしたがビット演算の結果が変数に入ったりはあるかも。型推量とかあるからね。まあブール値として使おうとしたところでコンパイルが通らなくなりなんでだろ~になって終わる。コンパイルが通らないからリリースもされない。気づくまでにどれくらいかかるかは人によるだろう。
確かに&はビット演算ですが今回の原因はビット演算だからではありません。&&はショートサーキット評価で左の値がfalseのときは右側が実行されませんが、&では左の値に関わらず右が実行されてしまいます。key_data_の定義はbase::Optional<KeyData> key_data_;となっており、base::Optionalというのはstd::optionalのChromium版の実装です。左側では key_data_.has_value() と値が存在しているかどうかをチェックした上で、右側で key_data_->label() とデータにアクセスしていますが、has_value()がfalseならアクセスすべきデータが存在しないのでundefined behaviourとなります。多分nullptrへのアクセスでクラッシュしますね。
あーnullアクセスか。これなら普通だな。勘違いしてた。メンバアクセスがアロー演算子 [github.io]と(若干良く分かってない)。if(!(key_data_ is null) && !key_data_.label().empty()){ return key_data_.label(); }相当か。
この辺null条件演算子が出来てからだいぶ楽になったなぁ。
unique_ptrとかならnullアクセスになるだろうけど、今回はOptionalだからnullアクセスにはならない。未初期化なデータ領域へのアクセスでのUB。
元コメと同じことを言ってますよ?
> アクセスすべきデータが存在しないのでundefined behaviourとなります。多分nullptrへのアクセスでクラッシュしますね。
UB(undefined behavior)であり、gcc/clang系のreleaseビルドなら大抵 nullptr でしょう。だから”多分”と言ってる。
C/C++ってJavaScriptとかの派生言語とは違って文中の評価順序は一部不定で頼るべからずな印象なのだけど、論理演算における短絡評価だけは明確な仕様なんですね。# 仕様と言いつつオーバーロードすると不定になるらしいけど
C/C++の不定・未定義の闇、怖い……
Cだと演算優先順位も微妙に違うから ことによっちゃ大事に
だからifの条件で実行と評価を同時にすんなって規約のとこもあるんだけどね。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
Stay hungry, Stay foolish. -- Steven Paul Jobs
なんで? (スコア:3, 参考になる)
`key_data_->label().empty()`に副作用がないなら条件付きか否かで変わらなくない?
と思ったが、C++だと&はビット演算で両方trueでもfalseになることがあるのか。
&&と&は条件付きかだけじゃなく評価の仕方が違うのね。
C#で両辺boolなら無視できるパフォーマンス上の問題でしかないからピンとこなかったわ。
Re: (スコア:0)
C#とかJavaでも両辺が整数とかだったりすると…
C#とかJavaだと評価の仕方が違うというかboolとそれ以外で事実上全然別の演算子ですね。
Re: (スコア:0)
C#は演算子オーバーロードがあるのでなんでもあり。
ただifの条件にbool以外は入らないからこういう問題はまず起こらない。
boolへの暗黙の型変換が定義されてれば起こせなくはないがまぁ起きない
Re: (スコア:0)
判定結果をブール値として変数に入れようとしたがビット演算の結果が変数に入ったりはあるかも。型推量とかあるからね。
まあブール値として使おうとしたところでコンパイルが通らなくなりなんでだろ~になって終わる。コンパイルが通らないからリリースもされない。気づくまでにどれくらいかかるかは人によるだろう。
Re: (スコア:0)
確かに&はビット演算ですが今回の原因はビット演算だからではありません。
&&はショートサーキット評価で左の値がfalseのときは右側が実行されませんが、&では左の値に関わらず右が実行されてしまいます。
key_data_の定義は
base::Optional<KeyData> key_data_;
となっており、base::Optionalというのはstd::optionalのChromium版の実装です。
左側では key_data_.has_value() と値が存在しているかどうかをチェックした上で、右側で key_data_->label() とデータにアクセスしていますが、has_value()がfalseならアクセスすべきデータが存在しないのでundefined behaviourとなります。多分nullptrへのアクセスでクラッシュしますね。
Re: (スコア:0)
あーnullアクセスか。これなら普通だな。勘違いしてた。
メンバアクセスがアロー演算子 [github.io]と(若干良く分かってない)。
if(!(key_data_ is null) && !key_data_.label().empty()){ return key_data_.label(); }
相当か。
この辺null条件演算子が出来てからだいぶ楽になったなぁ。
Re: (スコア:0)
unique_ptrとかならnullアクセスになるだろうけど、今回はOptionalだからnullアクセスにはならない。
未初期化なデータ領域へのアクセスでのUB。
Re: (スコア:0)
元コメと同じことを言ってますよ?
> アクセスすべきデータが存在しないのでundefined behaviourとなります。多分nullptrへのアクセスでクラッシュしますね。
UB(undefined behavior)であり、gcc/clang系のreleaseビルドなら大抵 nullptr でしょう。だから”多分”と言ってる。
Re: (スコア:0)
C/C++ってJavaScriptとかの派生言語とは違って文中の評価順序は一部不定で頼るべからずな印象なのだけど、
論理演算における短絡評価だけは明確な仕様なんですね。
# 仕様と言いつつオーバーロードすると不定になるらしいけど
C/C++の不定・未定義の闇、怖い……
Re: (スコア:0)
Cだと演算優先順位も微妙に違うから ことによっちゃ大事に
Re: (スコア:0)
だからifの条件で実行と評価を同時にすんなって規約のとこもあるんだけどね。