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

时间:2019-03-30 20:24:07

标签: c++ vector move-semantics

std::move在单个矢量元素上的行为是什么? 例如(以下是非常简化的代码)

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

我通常使用复制构造函数和删除函数,在某些情况下编译器会优化移动(合成)而不使用复制构造函数吗?

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

template< class T >
class Foo
{
};

vector< Foo< T > > v1, v2;

v2.emplace_back( std::move( v1[ 2 ] );

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

请阐明此问题。

1 个答案:

答案 0 :(得分:0)

移动语义有两个工作:

  • 表明资源的所有权(例如某些分配的内存,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 now\n"; 
    if(a.size() == 0)
        std::cout << "a.size() is zero now\n"; 
}

在我的系统上,使用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 now\n"; 
    if(a.value.size() == 0)
        std::cout << "a.size() is zero now\n"; 
}