61

2つのSTLベクトルがAあり、のすべての要素をクリアし、のすべての要素をに移動してからクリアBしたいと思います。簡単に言えば、私はこれをやりたいです:ABAB

std::vector<MyClass> A;
std::vector<MyClass> B;
....
A = B;
B.clear();

かなり長くなる可能性があるため、この操作を実行するBには時間がかかります。ここで、は定数で、はです。もっと効率的な方法があるのではないかと思っていました。私が考えることができることの1つは、ポインターとして定義し、一定時間内にポインターをコピーしてクリアすることです。k*O(N)kNmax(size_of(A), size_of(B))ABB

4

8 に答える 8

108

C ++ 11を使用すると、次のように簡単になります。

A = std::move(B);

Aこれで、以前はによって保持されていた要素が含まれ、B現在はB空になっています。これにより、コピーが回避されます。内部表現がからBに移動されるだけなAので、これがO(1)解決策です。

C ++ 03に関しては、Prætorianが述べているように、ベクトルを交換することができます。std::swap関数の特殊化がありstd::vector、引数としてsを取ります。これにより、内部表現が効果的に交換されるため、それらが保持する要素のコピーを作成する必要がなくなります。この関数はO(1)複雑でも機能します。

于 2012-09-27T02:58:09.527 に答える
16

C ++ 11コンパイラを使用している場合は、に移動できBますA

A = std::move(B);

古いコンパイラを使用している場合はswap、2つだけ

A.swap(B);

どちらの場合も、O(N)操作はの内容をクリアすることだけですA。前者の場合、クリアは割り当て自体の間に行われますが、後者の場合Bは、スコープ外になったときに行われます(内容が交換されたため)。

于 2012-09-27T02:59:21.787 に答える
5

2つのSTLベクトルAとBがあり、Aのすべての要素をクリアし、Bのすべての要素をAに移動してから、Bをクリアしたいと思います。

これは、の組み合わせで実行できますswap。最初の交換AB前半。次にswap、を空にするか、std::vector<>B呼び出しますclear()。違いはclear()、メモリを解放せず、オブジェクトを破棄するだけであるということです。

std::vector<int> a, b; // initialize them somehow
swap(a,b);

// clear b without releasing the memory:
std::size_t capacity = b.capacity();
b.clear();
assert(b.capacity()==capacity);

// or release the memory
std::vector<int>().swap(b);
assert(b.capacity()==0);
于 2012-09-27T03:13:29.297 に答える
4

ベクトルでclearを呼び出すだけで、o(1)時間がかかります。これは、clearは何もしないためです。Aに割り当てた後、本当にBをクリアしたい場合は、次のようにすることができます。

A.swap(B);
{
    std::Vector<..> C;
    c.swap(B);
}
于 2012-09-27T03:17:41.737 に答える
4

std::moveは正常に機能します。これが同じもののサンプルコードです

    vector<int> v1 = {1,2,3,10,20,30,100,200,300,999};
    vector<int> v2;

    cout << "Size of v1 before move = " << v1.size() << endl;
    cout << "Capacity of v1 before move = " << v1.capacity() << endl;

    v2 = std::move(v1);

    cout << "Size of v2 after move = " << v2.size() << endl;
    cout << "Capacity of v2 after move = " << v2.capacity() << endl;

    cout << "Size of v1 after move = " << v1.size() << endl;
    cout << "Capacity of v1 after move = " << v1.capacity() << endl;

-----------Output-------------------------
Size of v1 before move = 10
Capacity of v1 before move = 10
Size of v2 after move = 10
Capacity of v2 after move = 10
Size of v1 after move = 0
Capacity of v1 after move = 0
于 2018-05-17T11:46:32.183 に答える
2

スワップ機能はこれを行います。

#include <iostream>
#include <iterator>
#include <vector>

int main(int argc, char* argv)
{
  std::vector<int> A;
  std::vector<int> B;

  for (int i = 0; i < 10; ++i)
  {
     B.push_back(i);
  }

  std::cout << "Before swap\n";
  std::cout << "A:";
  std::copy(A.begin(), A.end(), std::ostream_iterator<int>(std::cout, " "));
  std::cout << "\nB:";
  std::copy(B.begin(), B.end(), std::ostream_iterator<int>(std::cout, " "));
  std::cout << "\n";

  A.swap(B);
  B.clear();

  std::cout << "After swap\n";
  std::cout << "A:";
  std::copy(A.begin(), A.end(), std::ostream_iterator<int>(std::cout, " "));
  std::cout << "\nB:";
  std::copy(B.begin(), B.end(), std::ostream_iterator<int>(std::cout, " "));
  std::cout << "\n";
}

出力

Before swap
A:
B:0 1 2 3 4 5 6 7 8 9 
After swap
A:0 1 2 3 4 5 6 7 8 9 
B:
于 2012-09-27T03:07:58.997 に答える
2

ベクトルをstd::moveまたはstd::swapできない場合(たとえば、AとBは関連しているが、タイプが異なるため、おそらくconstのみが異なるため)、次のことができます。

std::vector<MyClass>       A;
std::vector<const MyClass> B;
// ...
for( auto& a : A )
{
    B.emplace_back( std::move( a ) );
}

これにより、Aに同じ数の要素が残りますが、それらはすべて不確定な状態にあることに注意してください(つまり、それらは割り当てまたは破棄できますが、読み取ることはできません)。

于 2016-09-22T02:08:11.267 に答える
2

コメントする担当者が不足していますが、 https : //en.cppreference.com/w/cpp/container/vector/operator%3Dvoid.pointerが正しいことを述べておきます。特に...

2)ムーブ代入演算子。移動セマンティクスを使用して、コンテンツを他のコンテンツに置き換えます(つまり、他のデータが他のデータからこのコンテナーに移動されます)。その他は、その後有効ですが指定されていない状態になります。

したがって、プラエトリアニの答えは基準ごとに間違っています。ただし、少なくともMSVCの場合は、実装によってリストがクリアされるため、十分です(おそらくほとんどの場合に当てはまります)。

興味深いのは、ムーブコンストラクターを宣言しているため、暗黙のムーブ代入演算子が宣言されないことです。したがって、std::vectorはムーブ代入演算子を宣言する必要があることを「知っています」。

于 2019-01-09T07:06:03.340 に答える