C++ STL 向量:移动向量的所有元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12613428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:25:00  来源:igfitidea点击:

STL vector: Moving all elements of a vector

c++stlstdvector

提问by aminfar

I have two STL vectors Aand Band I'd like to clear all elements of Aand move all elements of Bto Aand then clear out B. Simply put, I want to do this:

我有两个 STL 向量AB我想清除 的所有元素A并将所有元素移动BA,然后清除B。简单地说,我想这样做:

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

Since Bcould be pretty long, it takes k*O(N)to do this operation, where kis a constant, and Nis max(size_of(A), size_of(B)). I was wondering if there could be a more efficient way to do so. One thing that I could think of is to define Aand Bas pointers and then copy pointers in constant time and clear out B.

由于B可能很长,因此需要k*O(N)执行此操作,其中k是常数,而Nmax(size_of(A), size_of(B))。我想知道是否有更有效的方法来做到这一点。我能想到的一件事是将A和定义B为指针,然后在恒定时间内复制指针并清除B

回答by mfontanini

Using C++11, it's as simple as:

使用 C++11,它很简单:

A = std::move(B);

Now Acontains the elements that were previously held by B, and Bis now empty. This avoids copying: the internal representation is simply moved from Bto A, so this is an O(1)solution.

现在A包含以前所持的元素B,而B现在是空的。这避免了复制:内部表示只是从Bto移动A,所以这是一个O(1)解决方案。

As for C++03, as Pr?torian states, you could swap the vectors. There is a specialization of the std::swapfunction, which takes std::vectors as its arguments. This effectively swaps the internal representation, so you end up avoiding creating copies of the elements held by them. This function works in O(1)complexity as well.

至于 C++03,正如 Pr?torian 所说,你可以交换向量。该std::swap函数有一个特化,它以std::vectors 作为参数。这有效地交换了内部表示,因此您最终避免创建它们持有的元素的副本。此函数也适用于O(1)复杂性。

回答by Praetorian

If you have a C++11 compiler you can move Binto A.

如果您有 C++11 编译器,则可以B进入A.

A = std::move(B);

If you're working with an older compiler, just swapthe two

如果您使用的是较旧的编译器,则只需swap两个

A.swap(B);

In both cases, the only O(N)operation will be clearing the contents of A. In the first case the clearing will be done during the assignment itself, while in the second it will happen when Bgoes out of scope (since the contents were swapped).

在这两种情况下,唯一的O(N)操作将清除 的内容A。在第一种情况下,清除将在分配本身期间完成,而在第二种情况下,它会在B超出范围时发生(因为内容已交换)。

回答by David Rodríguez - dribeas

I have two STL vectors A and B and I'd like to clear all elements of A and move all elements of B to A and then clear out B.

我有两个 STL 向量 A 和 B,我想清除 A 的所有元素并将 B 的所有元素移动到 A,然后清除 B。

This can be done with a combination of swap. First swap Aand Bfor the first half. Then swapan empty std::vector<>with Bor call clear(). The difference is that clear()will not release the memory, but only destroy the objects:

这可以通过组合来完成swap。第一次交换AB上半场。然后swap一个空的std::vector<>withB或 call 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);

回答by mogulkahn

just call clear on vector will take o(1) time, since clear will do nothing, If you really want to clear B after assign it to A, you could do the following

只在 vector 上调用 clear 需要 o(1) 时间,因为 clear 不会做任何事情,如果你真的想在将它分配给 A 后清除 B,你可以执行以下操作

A.swap(B);
{
    std::Vector<..> C;
    c.swap(B);
}

回答by metal

If you can't std::move or std::swap the vectors (e.g., because A and B are related but different types, perhaps differing only by const), you can do:

如果您不能 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 ) );
}

Note that this leaves A with the same number of elements, but they are all in an indeterminate state (i.e., they can be assigned to or destructed, but not read).

请注意,这使 A 具有相同数量的元素,但它们都处于不确定状态(即,它们可以分配或销毁,但不能读取)。

回答by Sameer Ahuja

std::move works fine. Here is the sample code for the same

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

回答by Jason

The swap function does this.

交换函数就是这样做的。

#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";
}

The output

输出

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:

回答by redfeatherplusplus

I lack rep to comment, but I want to mention that per: https://en.cppreference.com/w/cpp/container/vector/operator%3Dvoid.pointer is right. In particular...

我缺乏评论的代表,但我想提一下:https://en.cppreference.com/w/cpp/container/vector/operator%3D void.pointer 是正确的。特别是...

2) Move assignment operator. Replaces the contents with those of other using move semantics (i.e. the data in other is moved from other into this container). other is in a valid but unspecified state afterwards.

2) 移动赋值运算符。使用移动语义将内容替换为 other 的内容(即 other 中的数据从 other 移动到此容器中)。other 之后处于有效但未指定的状态。

Thus Praetorian's answer is wrong per standard. However, for MSVC at least, is good enough because the implementation clears the list anyway (Probably true for most).

因此,按照标准,Praetorian 的回答是错误的。但是,至少对于 MSVC 来说,已经足够好了,因为无论如何实现都会清除列表(对于大多数人来说可能是正确的)。

Something interesting is that since we declare a move constructor, no implicit move assignment operator will be declared. Thus we "know" that std::vector must declare a move assignment operator.

有趣的是,由于我们声明了移动构造函数,因此不会声明隐式移动赋值运算符。因此我们“知道” std::vector 必须声明一个移动赋值运算符。