9

検索しましたが、「いつ」使用するかの答えが見つかりません。余分なコピーを節約できるので、良いと聞いています。私は持っていたすべてのクラスにそれを入れてみましたが、いくつかのクラスではそれが意味をなさないようでした:S LValues と RValues と std::move 対 std::copy 対 memcpy に関する無数のチュートリアルを読みましたvs. memmove など。throw() についても読んでいますが、それをいつ使用するかはわかりません。

私のコードは次のようになります:

struct Point
{
    int X, Y;

    Point();
    Point(int x, int y);
    ~Point();

    //All my other operators here..
};

次に、そのようなクラス配列があります(RAIIのようなもの):

class PA
{
    private:
        std::vector<Point> PointsList;

    public:
        PA();
        //Variadic Template constructor here..
        ~PA();
        //Operators here..
 };

ムーブ コンストラクターとコピー コンストラクターを使用する必要がありますか? ポイントクラスで持っていたのですが、変な感じがしたので外しました。それからPAクラスで持っていたのですが、あまり役に立たないと思ったので外しました。次に、私のビットマップ クラスで、コンパイラはポインター メンバーを持っているがオーバーロードがないことについて不平を言っていたので、次のようにしました。

//Copy Con:
BMPS::BMPS(const BMPS& Bmp) : Bytes(((Bmp.width * Bmp.height) != 0) ? new RGB[Bmp.width * Bmp.height] : nullptr), width(Bmp.width), height(Bmp.height), size(Bmp.size), DC(0), Image(0)
{
    std::copy(Bmp.Bytes, Bmp.Bytes + (width * height), Bytes);
    BMInfo = Bmp.BMInfo;
    bFHeader = Bmp.bFHeader;
}

//Move Con:
BMPS::BMPS(BMPS&& Bmp) : Bytes(nullptr), width(Bmp.width), height(Bmp.height), size(Bmp.size), DC(0), Image(0)
{
    Bmp.Swap(*this);
    Bmp.Bytes = nullptr;
}

//Assignment:
BMPS& BMPS::operator = (BMPS Bmp)
{
    Bmp.Swap(*this);
    return *this;
}

//Not sure if I need Copy Assignment?

//Move Assignment:
BMPS& BMPS::operator = (BMPS&& Bmp)
{
    this->Swap(Bmp);
    return *this;
}

//Swap function (Member vs. Non-member?)
void BMPS::Swap(BMPS& Bmp) //throw()
{
    //I was told I should put using std::swap instead here.. for some ADL thing.
    //But I always learned that using is bad in headers.
    std::swap(Bytes, Bmp.Bytes);
    std::swap(BMInfo, Bmp.BMInfo);
    std::swap(width, Bmp.width);
    std::swap(height, Bmp.height);
    std::swap(size, Bmp.size);
    std::swap(bFHeader, Bmp.bFHeader);
}

これは正しいです?私は何か悪いことをしましたか?throw() は必要ですか? 私の代入演算子とムーブ代入演算子は、実際にはそのように同じである必要がありますか? コピー課題は必要ですか?ああ、たくさんの質問があります :c 私が最後に質問したフォーラムではすべてに答えられなかったので、混乱したままでした。最後に、Bytes に unique_ptr を使用する必要がありますか? (これはバイト/ピクセルの配列です。)

4

3 に答える 3

16

Scott Meyer のブログには、いくつかの優れた考えがあります。

まず、すべてのコピー リクエストをムーブに置き換えることができるわけではありません。最適化の対象となるのは、右辺値のコピー リクエストのみです。第 2 に、すべての型がコピー操作よりも効率的な移動操作をサポートしているわけではありません。例は std::array です。第 3 に、効率的な移動操作をサポートするタイプでさえ、一部の時間しかサポートしない場合があります。適切なケース: std::string。移動をサポートしますが、std::string が SSO (小さな文字列の最適化) を使用して実装されている場合、小さな文字列はコピーするのと同じくらい移動にコストがかかります!

おそらく、それに応じてタイプを分類してから、移動セマンティクスが必要なすべてを決定できます。コンパイラの自動生成移動 ctors/代入演算子には制限があることに注意してください。これは、移動メンバーを明示的に指定する場合に役立ちます。

移動メンバーを明示的に指定しないクラスの場合、面倒な点がいくつかあります。rvaluesからのコピーを禁止する明示的/暗黙的に削除された move メンバーの問題もあります。Moveメンバーの暗黙的な生成に関する問題の非常に価値のあるソースは、Stroustrup のTo Move or Not to Moveというタイトルの論文で見つけることができます。

移動セマンティクスによる例外処理については、Dave Abraham の投稿Exceptionally Movingをお勧めします。

時間があれば、いくつかの例を挙げてこの回答に戻ってみます。当分の間、上記のリンクが開始に役立つことを願っています。

于 2012-06-18T05:27:55.717 に答える
5

何よりもまず、可能な限り「ゼロのルール」を使用してください。「3/5/0 の法則」と「C-20」を参照してください。

したがって、あなたの「奇妙な」感覚は正しかったです。明示的なコピー/移動演算子は必要PointありPAません。それ以外の場合、dirkgentlydirvineの回答とそれらの参照は、より詳細な理解のための優れた読み物です。

明示的な移動演算子を提供するBMPSことは確かに良い考えです。

于 2018-10-19T08:07:09.190 に答える
3

移動は、スピード以上のことを可能にする非常に優れたツールです。move を使用すると、(明らかに) オブジェクトを移動し、(空の死骸、またはより正確にはデフォルトで構築されたオブジェクトを除いて) 何も残しません。これにより、移動オブジェクトが優先される場合、プログラムの所有権と設計についてより慎重に考える必要があります。一部のオブジェクトへの複数のアクセスや共有の代わりに、移動により、誰がいつオブジェクトを持っているかを明確に考慮する必要があります。

Bjarne Stroustrup が以前に述べたように、すべてを共有したり、どこにでもポインタを置いたりするのはやめるべきです。ポインターを使用する場合は、絶対に所有権を共有したい場合 (多くの場合共有しない場合) を除き、shared_ptr ではなく unique_ptr を使用します。Unique_ptr とその移動のみの (とにかく削除されたコピー) コンストラクターは、移動を提供し、決してコピーしないオブジェクトの良い例です。

Move は優れており、move コンストラクターを作成することは非常に良い考えです。msvc が追いつき、コンパイラーによって生成された (コピー/割り当てなど) コンストラクターで削除された/デフォルトのデコレーターを許可すると、さらに効果的です。以前に削除されたメンバーへのアクセス試行などのエラーは、ここでは非常に役立ちます。一部のコンストラクターを非公開にするだけでは、コード管理者にとってあまり明確な意図がありません。コピーはOKだが移動が優先される場合、コンパイラは可能な場合は移動することを選択することを願っています(つまり、一部のコンパイラでは移動または emplace_back が妥当な場合は vector.push_back でテストし、即座にパフォーマンスを向上させます)、したがってコピーコンストラクタオブジェクトでも定義された移動コンストラクターが自動的に選択され、パフォーマンスが向上します(現在猛威を振るっている SSO の議論はすべて無視します)。これは熟読するためのまともな答えです

ブースト メーリング リストには、move/copy と pass by value/reference の長所/短所についての非常に重いスレッドがいくつかあり、詳細情報を探している場合は、すべて同様の問題について非常に話し合っています。

于 2012-06-18T17:24:34.403 に答える