64

メンバー変数、コピー可能および移動可能なタイプのそれぞれ、および対応するセッター関数をX持つクラスについて考えてみます。C ++ 98では、の定義は次のようになります。NNX

class X
{
public:
    void set_a(A const& a) { _a = a; }
    void set_b(B const& b) { _b = b; }
    ...
private:
    A _a;
    B _b;
    ...
};

上記のクラスのセッター関数はX、左辺値と右辺値の両方の引数にバインドできます。実際の引数によっては、これにより一時的なものが作成さ、最終的にはコピーの割り当てが発生する可能性があります。このため、コピーできないタイプはこのデザインではサポートされていません。

C ++ 11では、移動セマンティクス、完全な転送、およびユニバーサル参照(Scott Meyersの用語)があり、次のように書き直すことで、セッター関数をより効率的かつ一般的に使用できます。

class X
{
public:
    template<typename T>
    void set_a(T&& a) { _a = std::forward<T>(a); }

    template<typename T>
    void set_b(T&& b) { _b = std::forward<T>(b); }
    ...
private:
    A _a;
    B _b;
    ...
};

ユニバーサル参照は、/ non -、/ non- const、および一般に任意の変換可能なタイプにバインドできるため、一時的なものの作成を回避し、値をに直接渡すことができます。コピー不可能な移動可能なタイプがサポートされるようになりました。おそらく望ましくないバインディングは、を介して、またはを介して排除できます。constvolatilevolatileoperator =static_assertstd::enable_if

だから私の質問は:設計ガイドラインとして、C ++ 11のすべての(たとえばほとんどの)セッター関数は、ユニバーサル参照を受け入れる関数テンプレートとして作成する必要がありますか?

より厄介な構文と、これらのセッター関数でコードを記述するときにIntellisenseのようなヘルパーツールを使用できないことは別として、「可能な場合はいつでもユニバーサル参照を受け入れる関数テンプレートとしてセッター関数を書く」という仮定の原則に関連する欠点はありますか?

4

1 に答える 1

36

クラス A と B を知っているので、それらが可動かどうか、そしてこの設計が最終的に必要かどうかがわかります。のようなものstd::stringでは、ここでパフォーマンスの問題があることがわかっていない限り、既存のコードを変更するのは時間の無駄です。を扱っている場合はauto_ptr、それを取り出して使用する時が来ましたunique_ptr

より具体的なものがわからない場合は、通常、引数を値で受け取ることをお勧めします-

void set_a(A a) { _a = std::move(a); }

これにより、可動性以外は何も必要とせずに の任意のコンストラクターを使用できA、比較的直感的なインターフェイスが提供されます。

于 2013-01-07T14:10:25.223 に答える