0
class A
{
public:
    A()
    {
        cout << "A()" << endl;
    }

    A(const A&)
    {
        cout << "A(const A&)" << endl;
    }

    A(A&&)
    {
        cout << "A(A&&)" << endl;
    }

    A& operator=(const A&)
    {
        cout << "A(const A&)" << endl;
    }

    A& operator=(A&&)
    {
        cout << "A(const A&&)" << endl;
    }

    ~A()
    {
        cout << "~A()" << endl;
    }
};

A&& f_1()
{
    A a;
    return static_cast<A&&>(a);
}

A f_2()
{
    A a;
    return static_cast<A&&>(a);
}

int main()
{
    cout << "f_1:" << endl;
    f_1();
    cout << "f_2:" << endl;
    f_2();
}

出力は次のとおりです。

f_1:
A()
~A()
f_2:
A()
A(A&&)
~A()
~A()

サンプルコードは、f_1()がf_2()よりも効率的であることを明らかに示しています。

だから、私の質問は:

関数を常にsome_return_type&&f(...);として宣言する必要があります。some_return_typeの代わりにf(...); ?

私の質問に対する答えが正しい場合、別の質問が続きます。

some_return_type f(...);として宣言された多くの関数があります。C ++の世界では、それらを最新の形式に変更する必要がありますか?

4

2 に答える 2

6

関数をBigStruct&&foo(…);として宣言するのは良い習慣ですか。

恐ろしい練習。lvalue-referencesと同様に、実行しているのはローカルオブジェクトへの参照を返すことです。呼び出し元が参照を受け取るまでに、参照されたオブジェクトはすでになくなっています。

some_return_type f(...);として宣言された多くの関数があります。C ++の世界では、それらを最新の形式に変更する必要がありますか?

現代のフォームは、それらがすでに構築されているフォームです(リターンタイプのみを考慮)。誰もがすべてのコードを書き直さないように、共通のフォームをより効率的にするために標準が変更されました。

現在、オブジェクトを作成するときのvoid f( type& t )代わりに、最新ではないバージョンがあります。推論するためのより単純なインターフェースを提供し、より単純なユーザーコードを提供するため、最新の形式に変更したいもの:type f()f type f()

ユーザーは、オブジェクトが変更された作成されたかを考える必要はありません。

void read_input( std::vector<int>& );

それはベクトルを追加または置換しますか?

そして、発信者コードをより簡単にします:

auto read_input();

対。

std::vector<int> v; 
read_input(v);
于 2012-05-05T16:07:34.280 に答える
0

f_2コンパイラがNRVOを適用するのを防いいます。キャストを削除し、最適化を有効にしてコンパイルすると、同じように効率的であることがわかります。参照へのキャストはまったく必要ありません。では意味がありませんf_2

于 2014-03-06T14:53:14.723 に答える