2017-02-10 12 views
2

私はリソース管理オブジェクトをベクトルに追加するときに、なぜ追加の移動コンストラクタ操作を取得するのか理解しようとしています。ここでオブジェクトをベクターに移動するときに、余分な移動コンストラクタ操作が必要なのはなぜですか?

は、私のリソース管理クラスである:

class Resource 
{ 
public: 
    Resource() { 
     own_ = true; 
     id_ = next_id++; 
     std::cout << "Resource " << id_ << " constructed\n"; 
    } 

    Resource(Resource&& c) { 
     std::cout << "Move constructed from " << c.id_ << " to " << id_ << "\n"; 
     swap(*this, c); 
    } 

    ~Resource() { 
     if (own_) { 
      std::cout << "Resource " << id_ << " destructed\n"; 
     } 
    } 

    Resource& operator=(Resource&& c) { 
     std::cout << "Move assigned from " << c.id_ << " to " << id_ << "\n"; 
     swap(*this, c); 
     return *this; 
    } 

    void swap(Resource& a, Resource& b) { 
     std::swap(a.id_, b.id_); 
     std::swap(a.own_, b.own_); 
    } 

    Resource(Resource const&) = delete; 
    auto operator=(Resource const&)->Resource = delete; 
    static int next_id; 
private: 
    bool own_ = false; 
    int id_; 
}; 
int Resource::next_id = 1; 

そして、ここでは、私は2つのオブジェクトを作成し、リソースの私のベクトルにそれらを移動しています主な機能です:

int main() { 
    std::vector<Resource> resources; 

    Resource a, b; 
    resources.push_back(std::move(a)); 
    resources.push_back(std::move(b)); 

    return 0; 
} 

そしてここにはあります出力。最初の4行は私が期待したようなものですが、最後の行は何かがベクトル内で並べ替えまたはソートされているような余分な操作のようです。

Resource 1 constructed 
Resource 2 constructed 
Move constructed from 1 to -842150451 
Move constructed from 2 to -842150451 
Move constructed from 1 to -842150451 
+0

http://stackoverflow.com/questions/23717151/why-emplace-back-is-faster-than-push-back –

+0

コピーコンストラクタが 'delete'dでない場合は、 2つの動きの構造を見たが、[非常に異なる理由](http://stackoverflow.com/q/8001823/241631)。 – Praetorian

+0

私の最後のコメントは、あなたのコピーコンストラクタが(デフォルトでは)暗黙のうちに削除されているからだと言っているはずです。 – Praetorian

答えて

4

ベクトルが育ったので、あなたは追加の移動コンストラクタの呼び出しを参照してください。2つのリソースオブジェクトが、私の出力がある - しかし、予想通りのベクトルの最終的な内容があります。したがって、最初の移動は初めてベクトルに挿入され、無関係の移動は、その要素を次の要素をベクトルに収めるために作成された新しいバッファに移動することです。

通常、空のベクターがある場合は、push_packは1つの空き領域を割り当て、その中に要素を追加します。次にpush_backと呼ぶと、容量を倍にして新しいストレージを割り当て、すべてを古いストレージから新しいストレージに移動/コピーします。 size() == capacity()の場合は、push_backを呼び出すたびに、ベクターは新しい記憶域を割り当ててすべてを新しい記憶域に移動し、新しい要素を追加する必要があります。

関連する問題