移动单个矢量元素上的语义

Move semantics on individual vector elements

本文关键字:语义 元素 单个矢 移动      更新时间:2023-10-16

单个向量元素上std::move的行为是什么?例如(大致简化的代码如下(

这会执行正确的移动吗,我需要erase()移动的元素吗?

我通常使用复制构造函数

和删除,编译器是否会针对移动(合成(进行优化,而不是在某些情况下使用复制构造函数?

我尝试使用智能指针包装器,但没有看到显着的加速。移动语义看起来像我想要使用的。

template< class T >
class Foo
{
};
vector< Foo< T > > v1, v2;
v2.emplace_back( std::move( v1[ 2 ] );

我没有看到使用移动操作的显着加速,我认为我已经正确实现了移动构造函数和移动赋值运算符。

请阐明这个问题。

移动语义有两个工作:

  • 指示资源的所有权(例如某些分配的内存、FILE* 指针或流(已易手
  • 在上述情况下避免不必要的副本。

例如,假设我们有一个向量:

vector<int> a; 
for(int i = 0; i < 10000; i++) { 
    a.push_back(i); 
}

如果我写:

vector<int> b = a;

这会复制a中的每个元素,因此操作速度很慢。但是,如果我写

vector<int> b = std::move(a); 

a中的任何元素都不会被复制,这最终会快得多。但是,a不再拥有这些元素。我们可以使用以下代码进行演示:

#include <vector>
#include <iostream>
int main() {
    using std::vector;
    vector<int> a = {1, 2, 3};
    vector<int> b = std::move(a); 
    if(a.data() == nullptr) // This should be true now
        std::cout << "a.data() is null nown"; 
    if(a.size() == 0)
        std::cout << "a.size() is zero nown"; 
}

在我的系统上,使用 gcc 和 clang 打印此代码

a.data() is null now
a.size() is zero now

即使您有一个包装类,这也适用:

#include <vector>
#include <iostream>
template<class T>
class Wrapper {
   public:
    // Because all the members of Wrapper are public,
    // the compiler automatically generates move and copy constructors
    T value; 
};

int main() {
    using std::vector;
    Wrapper<vector<int>> a = {{1, 2, 3}};
    Wrapper<vector<int>> b = std::move(a); 
    // Same output as before
    if(a.value.data() == nullptr)
        std::cout << "a.data() is null nown"; 
    if(a.value.size() == 0)
        std::cout << "a.size() is zero nown"; 
}