11

uint8_t のベクトルを構築するファクトリ クラスを実装しています。結果のベクトルを返すときに移動セマンティクスを利用できるようにしたいと考えています。これは機能しているように見えますが、これが私が望むことを達成する正しい方法であるとは確信していません。

返された自動変数が右辺値と見なされ、呼び出しコードの移動コンストラクターを使用する方法の例をかなり見てきましたが、私の例では、返されるオブジェクトはメンバーです。呼び出し元が戻り値を移動コンストラクターに入れると、メンバーの内容が失われることはわかっています。これがまさに私が望んでいることです。

私はそれを次のように書きました:

#include <cstdint>
#include <iostream>
#include <vector>

class Factory
{
public:
    std::vector<uint8_t> _data;

    Factory(std::size_t size) :
        _data(size, 0)
    {
    }

    void buildContent(int param)
    {
        // perform operations on the contents of _data
    }

    std::vector<uint8_t> && data()
    {
        return std::move(_data);
    }
};

int main()
{
    Factory factory(42);
    factory.buildContent(1);
    std::vector<uint8_t> temp(factory.data());
    std::cout << "temp has " << temp.size() << " elements" << std::endl;
    std::cout << "factory._data has " << factory._data.size() << " elements" << std::endl;

    return 0;
}

編集:

ああ、サンプル コードは次のように出力します。

temp has 42 elements
factory._data has 0 elements
4

3 に答える 3

8

まず第一に、あなたが望むものを決める必要があります。本当にインスタンスからデータを吸い出したいですか? もしそうなら、あなたが持っているものはその罰金を達成します。一方で、それは非常に危険に見えます。あなたができることは、参照修飾子を使用して、インスタンス自体が右辺値参照である場合にのみ右辺値参照を返すことを強制することです:

std::vector<uint8_t> && data() && // called on rvalue
{
    return std::move(_data);
}

// return lvalue ref or value
std::vector<uint8_t>& data() & // called on lvalue
{
    return _data;
}

結局、それはすべて、解決しようとしている問題に依存しますが、それはあなたの質問からは明らかではありません。

于 2013-10-02T09:35:17.337 に答える
2

コンパイラに this ( &&after メソッド) への右辺値参照がある場合は、それを使用することをお勧めします。@juanchopanzaの回答を参照してください。

そうでない場合は、まず、data()移動していることを明確にする必要があります。これを行うにはいくつかの方法があります。

まず、非メンバー メソッド ( friends) は on をオーバーライドできます&&。したがって、次の構文を取得できます。

std::vector<uint8_t> temp(get_data( std::move(factory) );

where get_datahas&&&overload はfactory型に基づいており、それに基づいて移動するかしないかのいずれかです。

次に、有効期限延長の問題に対してastd::vector<uint8_t>ではなくa を返します。`std::vector<uint8_t>&&ランタイム コストはゼロからわずかの間ですが、バグが除去されたことには価値があります。

Ifがオブジェクトをcreate_factory返すFactory場合、これを行うと:

for( uint8_t x : get_data( create_factory() ) )

get_dataa を返すものは機能&&しませんが、一時的なものを返すものは問題なく動作します。

何が起こっている?さて、範囲ベースの for ループは、繰り返し処理しているものを参照にバインドするものとして定義されます。参照にバインドされた一時的な有効期間は延長されます。参照にバインドされた参照には、有効期間の延長はありません。どちらの場合も、create_factory関数の戻り値の有効期間は延長されません。

この&&場合、ベクトルへの参照はぶら下がったままになります。return-temporary の場合、factoryのベクトルが一時オブジェクトに移動され、その一時オブジェクトの有効期間が延長されます。

要するに、&&参照を返すことが良い考えになることはめったにありません。

于 2013-10-02T15:33:58.983 に答える
0

ベクトルで代入演算子を非表示にして、移動代入演算子のみを実装するのはどうですか (基本的にコピーを禁止します - それが必要な場合)。

そのため、次のようになります。

std::vector<uint8_t> temp(factory.data());

これに変更しない限りコンパイルされません:

std::vector<uint8_t> temp(std::move(factory));
于 2013-10-04T11:03:06.490 に答える