2

具体的には、次のうちどれを書くべきか迷っています。

{
    shared_ptr<GuiContextMenu> subMenu = items[j].subMenu.lock();
    if (subMenu)
        subMenu->setVisible(false);
}

また:

{
    if (items[j].subMenu.lock())
        items[j].subMenu.lock()->setVisible(false);
}

スタイルのガイドラインに従う必要はありません。最適化後、どちらを選択してもパフォーマンスに違いはないと思います。一般的に好まれるスタイルとその理由は何ですか?

編集: items[j].subMenu のタイプは boost::weak_ptr です。lock() は、そこから shared_ptr を作成します。上記の 2 つのバージョンには、一時的な shared_ptr の持続時間に関して実際にはあいまいな違いがあるため、あいまいさを解決するために 2 つの例を { 中括弧 } で囲みました。

4

10 に答える 10

7

別の方法:

if(shared_ptr<GuiContextMenu> subMenu = items[j].subMenu.lock()) {
    subMenu->setVisible(false);
}
//subMenu is no longer in scope

その場合、2番目のメソッドsubMenuweak_ptr2つの一時的なものを作成しますが、これは問題になる場合とそうでない場合があります。そして、最初のメソッドは、必要以上に広いスコープに変数を追加します。個人的には、ifステートメント内で代入を避けるようにしていますが、これは代入よりも有用だと感じる数少ないケースの 1 つです。

于 2010-04-27T22:02:55.207 に答える
4

この特定のケースでは、一時変数を含むバージョンを実際に使用する必要があります。その理由はパフォーマンスではなく、正確さです。基本的に、2 つのx.lock()呼び出しが同じ値を返すことは保証されません (たとえば、別のスレッドが 2 つの呼び出しの間にオブジェクトの最後の強い参照を解放した場合)。一時変数に強い参照を保持することで、それが消えないようにします。

それ以外:

  • コンパイラは通常、副作用がないことが証明されている (これは難しいですが、属性が役立つ場合があります) またはインライン化されていない限り、関数呼び出しを最適化することはできません。この場合、呼び出しには副作用があります。

  • 一時変数を使用すると、プログラムが短くなり、読みやすく、保守しやすくなります (たとえば、エラーが発生した場合は、1 か所で修正します)。

于 2010-04-27T22:15:58.930 に答える
2

最適化後もどちらの選択も変わらないというのは正しいと思います。

個人的には、呼び出しを連鎖させたり、関数呼び出しを関数呼び出し内に配置したりする場合など、コードが読みやすくなる場合は、新しい変数を宣言します。それが保守可能であり、コードが速度差なしで同じ効果を達成する限り、それはすべて読み取り可能なコードに要約されます。

編集:

mmyersは良いコメントを買いました。lock()はい、 1回だけではなく、2回呼び出すように注意してください。それらは、実装に応じて異なる効果をもたらします。

于 2010-04-27T21:34:39.267 に答える
1

選択は基本的にあなた次第ですが、注意すべき基本的なことは保守性です。

于 2010-04-27T21:53:31.240 に答える
1

この特定の例では、何をするかに依存すると思いますlock()。機能は高価ですか?関数が呼び出されるたびに異なるものを返すことができますか (最初はポインターを返し、2 回目は NULL を返すことができますか)? への 2 つの呼び出しの間にインターリーブできる別のスレッドが実行されていlock()ますか?

この例ではlock()、賢明な決定を下すために、コードの動作と残りのコードを理解する必要があります。

于 2010-04-27T21:55:46.013 に答える
1

戻り値がブール値以外の場合、それを中間変数に割り当てると、多くの場合、デバッグが簡素化されます。たとえば、次のようにステップ オーバーするとします。

if( fn() > 0 ) ...

事後にわかるのは、関数がゼロ未満の値、またはゼロ以上の値を返したことだけです。戻り値が正しくない場合でも、コードは機能しているように見える場合があります。デバッガーで検査できる変数に割り当てると、戻り値が予期されていたかどうかを判断できます。

戻り値がブール値の場合、実際の値はコード フローによって完全に暗黙的に示されるため、それほど重要ではありません。ただし、コードのメンテナンスの下では、後でその結果が必要になる場合があるため、いずれにしても習慣にすることを決定できます。

戻り値がブール値の場合でも、考慮すべきもう 1 つの問題は、関数に副作用が必要かどうか、およびこれが短絡評価の影響を受ける可能性があるかどうかです。たとえば、ステートメントでは次のようになります。

if( isValid && fn() ) ...

isValid が false の場合、関数は呼び出されません。

不注意なプログラマーによるメンテナンス中にコードが壊れる可能性がある状況は数多くあります (そして、メンテナンス作業を行うのは経験の浅いプログラマーです)。

于 2010-04-27T22:02:42.697 に答える
0

コードがより明確で読みやすくなり、エラーが発生しにくくなるため、ほとんどの場合、最初のコードを使用します。たとえば、2番目の例の括弧を忘れた:)この場合、実際には、2番目の例で行ったことを実行しますが、そのサブメニューを数回以上使用する必要がある場合は、コードを読みやすくするための最初のもの。パフォーマンスに関しては、どんな正気のコンパイラでもそれを最適化できると思います(おそらく、パフォーマンスに違いが見られなかったのはそのためです)。

また、mmyersが指摘したように、それはlock()が何をするかにも依存します。一般的に、それが単純なゲッターメソッドまたはそのようなものであれば、問題はありません。

于 2010-04-27T21:35:50.357 に答える
0

この場合、一時的なものを使用する必要があると思います。.lock() の実装が安価であることがわかっていても、それは変わる可能性があります。lock() を 2 回呼び出す必要がない場合は、そうしないでください。ここでの価値は、lock() の実装からコードを分離することです。そして、それは一般的に良いことです。

于 2010-04-27T22:20:05.103 に答える
0

好ましいスタイルとは、コードをより読みやすく保守しやすくするスタイルだと思います。あなたが複数のチームである場合、他の唯一の考慮事項は、読みやすさと保守の容易さのために、全員が同じスタイルを採用することは一般的に良い考えであるということです.

于 2010-04-27T22:09:03.817 に答える
0

あなたが好むものは何でも。私にとっては、どれだけ使用するかによって異なります。2 行の場合は、2 回とも書き出すことができますが、それ以上使用する場合は変数を作成します。ただし、このコードを維持し、見続ける必要があるのはおそらくあなた自身なので、あなたに合ったものを使用してください。もちろん、コーディング ガイドラインがある会社にいる場合は、それに従ってください。

于 2010-04-27T21:42:35.800 に答える