1

オーバーロードされた operator+= メンバー関数の存在を前提として、operator+ の標準的な形式は次のようになると想定していました。

const T operator+(const T& lhs, const T& rhs)
{
    return T(lhs) +=rhs;
}

しかし、これも機能することが指摘されました。

const T operator+ (T lhs, const T& rhs)
{
    return lhs+=rhs;
}

本質的に、このフォームは一時オブジェクトの作成を実装の本体から関数呼び出しに転送します。

2 つのパラメーターの型が異なるのは少しぎこちなく思えますが、2 番目の形式に問題はありますか? どちらかを優先する理由はありますか?

4

7 に答える 7

4

どちらの場合も、生成されたコードに大きな違いがあるかどうかはわかりません。

これらの2つの間で、私は(個人的に)最初の形式を好みます。それは意図をよりよく伝えるからです。これは、+ =演算子の再利用と、const&によってテンプレート化された型を渡すイディオムの両方に関するものです。

于 2008-09-23T01:43:26.897 に答える
2

読みやすさのために最初の形式を好みます。

最初のパラメーターがコピーされているのを見る前に、よく考えなければなりませんでした。私はそれを予期していませんでした。したがって、どちらのバージョンもおそらく同じくらい効率的であるため、読みやすいものを選択します。

于 2008-09-23T02:15:12.890 に答える
2

編集された質問では、最初の形式が優先されます。コンパイラは戻り値を最適化する可能性が高くなります (これは、T のコンストラクターにブレークポイントを配置することで確認できます)。最初の形式も両方のパラメータを const として取りますが、これはより望ましい方法です。

簡単な例として、このリンクなど、戻り値の最適化のトピックに関する研究: http://www.cs.cmu.edu/~gilpin/c++/performance.html

于 2008-09-23T01:39:58.807 に答える
1
const T operator+(const T& lhs, const T& rhs)
{
    return T(lhs)+=rhs;
}

簡潔にしたいのなら、なぜこれではないのですか?

于 2008-09-23T04:02:53.537 に答える
1

私の最初の考えは、引数として参照がスタックにプッシュされないため、2 番目のバージョンは最初のバージョンよりもはるかに高速である可能性があるということです。ただし、これはコンパイラに大きく依存し、たとえば、コンパイラが名前付き戻り値の最適化を実行するかどうかに依存します。

とにかく、疑問がある場合は、存在すらしない可能性があり、おそらく必要としない非常に小さなパフォーマンスの向上を決して選択しないでください。最初の最も明確なバージョンを選択してください。

于 2008-09-23T07:10:01.153 に答える
0

実際には、2番目が優先されます。C++ 標準で述べられているように、

3.7.2/2: 自動保存期間

名前付き自動オブジェクトに初期化または副作用のあるデストラクタがある場合、そのブロックの終了前に破棄されたり、未使用のように見えても最適化として削除されたりしてはなりません。 12.8 に規定されているように削除することができます。

つまり、名前のない一時オブジェクトはコピー コンストラクターを使用して作成されるため、コンパイラは戻り値の最適化を使用しない場合があります。ただし、2 番目のケースでは、無名の戻り値の最適化が許可されます。コンパイラが名前付きの戻り値の最適化を実装している場合、最適なコードは次のとおりです。

const T operator+(const T& lhs, const T& rhs)
{
    T temp(lhs);
    temp +=rhs;
    return temp;
}
于 2008-11-02T01:09:16.730 に答える
0

両方をインライン化すると (関数を転送するだけで、おそらく operator+=() 関数が行外にあるため)、区別のつかないコード生成に近づくと思います。とはいえ、最初のほうがより標準的です。2番目のバージョンは不必要に「かわいい」です。

于 2008-11-02T01:20:44.477 に答える