このC ++機能の名前は何ですか?


82

私はいくつかのC ++コードを書いていて、誤って関数の名前を省略していましたWSASocket。しかし、私のコンパイラはエラーを発生させずSOCKET、有効なソケットの代わりに整数値1に関連付けました。

問題のコードは次のようになっているはずです。

this->listener = WSASocket(address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);

しかし、代わりに、次のようになりました。

this->listener = (address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);

他の言語から来ているので、これある種の匿名型のようです。それが本当に機能である場合、機能の名前は何ですか?

その目的は何ですか?

どこから始めればいいのかわからないときは、探すのが難しいです。


3
+1、パブクイズのいい質問(または頭の体操が得意な人を雇いたい会社のためのぞっとするような面接の質問)。
バトシェバ2014年

8
コンマ演算子に関するウィキペディアの記事へのリンク。FWIW、一般的な使用法の1つは、forループ内で2つの副作用を取得することです*反復式, ala for(int i = 0、j = 0; i <10; ++ i、-j)... `
Tony Delroy

1
@ MichaelJ.Gray技術的にあなたは間違っています。動作を上書きしていません。想像してみてくださいi=0;j=0;x=i++,j=6;。xとjは6で、iはとにかく1です。i++の動作が上書きされると、0のままになります。ただし、各ステートメントが呼び出され、,すべての拡張機能に到達すると破棄され、次の疑似シーケンスポイントが呼び出されます。したがって、最初=は最後の後にパーツを割り当てるだけです,が、各ポイントが呼び出されます。とにかく:コンパイラが関数宣言の再定義について警告せず、代わりにコードを別の動作に変更する
理由がわかりません

5
あなたがオンになって警告との適切なコンパイラを使用する場合、それは例えば、そのような危険なコードについて警告しますgccg++して-Wall、オプション言う:warning: left-hand operand of comma expression has no effect [-Wunused-value]
サム・ワトキンス

3
したがって、私の意見では、この質問に対する最良の答えは「常に警告を有効にする」です。そうすると、コンパイラ自体がエラーがあることを説明し、何をしたかを教えてくれます。そして、この答えはあなたのためにも他の多くの問題を解決します。
サムワトキンス

回答:


151

コンマ演算子†は左側を評価し、その値を破棄して、結果として右側を生成します。WSA_FLAG_OVERLAPPEDは1であり、これは式の結果です。他のすべての値は破棄されます。ソケットは作成されません。


†過負荷でない限り。はい、過負荷になる可能性があります。いいえ、過負荷にしないでください。今すぐキーボードから離れてください!


9
+1、ブーストスピリットはコンマ演算子を非常に効果的にオーバーロードしますが、それはルールの非常に孤独な例外ですそれをしないでください
バトシェバ2014年

2
@Bathsheba Boost.Assignもコンマ演算子をオーバーロードしますが、C ++ 11以降誰がそれを使用しますか?
rubenvb 2014年

39
しかし、あなたは強力なコンマがどれほど恐ろしいものであるかについての最も良い説明を持っていました。容赦なく、嘲笑に満ちて、それはその振る舞いに恥ずかしがらずに私を見つめている間、数分間私のコードを悩ませました。
マイケルJ.グレイ


1
@ R.MartinhoFernandes-Eigenは、コンマ演算子も非常に効果的にオーバーロードします。使用例については、このSEの質問を参照してください。
デビッドハメン

22

コンマ演算子は、あなたのコードの意味を作っています。

this->listener = WSA_FLAG_OVERLAPPED;たまたま構文的に有効なものを効果的に設定しています。


3
構文的に有効であるだけでなく、Windows APIはタイプセーフではないため、有効な変換でもあります。
MSalters 2014年

5
@MSaltersは、POSIXがその点ではるかに優れているというわけではありません
chbaker0 2014年

1
そのため、単一の引数で呼び出すことができるコンストラクターは明示的である必要があります。そうすると、コンパイラエラーが発生し、開発者はこの奇妙な構造をもう一度確認する機会があります。
Matthieu M.

@MSaltersまあ、SOCKETのtypedefでunsigned intあり、WSA_FLAG_OVERLAPPEDあるintリテラル。のSOCKET同義語であった場合int、それは変換でさえありませんでした。
joker_vD 2014年

1
@Joker_vD:確かに。彼らがそれをtypedefにしたstruct __socket*としたら、バグは少なくなるでしょう。しかし、「知っている」ことSOCKETが不可欠なコードが多すぎます。
MSalters 2014年

21

コンパイラーは括弧内の各シーケンスポイントを順番に評価し、その結果が式の最終式WSA_FLAG_OVERLAPPEDになります。

コンマ演算子,は、C ++のシーケンスポイントです。カンマの左側の式は、右側の式が評価される前に完全に評価されます。結果は常に右側の値です。フォーム(x1、x2、x3、...、xn)の式がある場合、式の結果は常にxnです。


そこに説明を追加した後、それはより理にかなっています。最初は、シーケンスポイントの問題の関連性を完全には理解していませんでした。
マイケルJ.グレイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.