使用std::move

11

在使用 C++11 之前,我使用“swap-to-back”来避免深拷贝的开销,例如:

vector<vector<Object> > Objects;

for(/* some range */)
{
    vector<Object> v;
    for(/* some other range */)
    {
        v.push_back(/* some object */);
    }
    Objects.push_back(vector<Object>());
    Objects.back().swap(v);
}
我该如何使用 std::movev 移动到 Objects 中,以避免深度复制的开销,而不是使用 swap
我知道这里有很多解决方法,比如使用多维数组或直接插入到 Objects.back() 中,但我需要一个使用 std::move 的示例来理解它。

2
你为什么要创建 v 呢?为什么不直接在 Objects 中添加一个空向量,然后 Objects.back().push_back() 向其中添加元素呢?这样可以减少开销,同时更加简单。 - Ayjay
@Ayjay:请阅读问题的其余部分。 - Daniel
2个回答

17
Objects.push_back( std::move( v ) );

2
+1 表示你回答正确,但会得到较少的关注。 - sehe

16
vector<vector<Object> > Objects;

for(/* some range */)
{
    vector<Object> v;
    for(/* some other range */)
    {
        v.push_back(/* some object */);
    }
    Objects.push_back(std::move(v));
}

但是这样会让变量 v 被遗留下来。我理解 std::move 应该是有一定破坏性的。 - Daniel
2
@Dani:不要假设,试一下。实际上,阅读vector::vector(vector&&)的源代码也足够了。语义与您的std::swap版本非常接近——但在一般情况下更优雅、可能更高效。 - sehe
@sehe:通常我的对象都有简单的构造函数。为了避免使用具有非平凡构造函数的对象可能带来的问题,我在使用这些对象时总是使用指针。 - Daniel
9
在sehe的代码中,进行了move操作之后,你想用v做什么?他所做的只是对其进行了销毁。由于~vector<Object>()没有前置条件,因此在move之后对其进行销毁是完全可以的。你还有其他想要做的事情吗?如果有,你可以通过一些简单的操作,例如v.clear()vector<Object>::clear()也没有前置条件,因此可以在move之后调用)将其置于已知状态。 - Howard Hinnant
1
@Dani:“但这样会留下v。我理解std::move应该有点破坏性。” - 任何时候你有意义地使用std::move,都会留下相关的变量。它的整个目的是将不是右值的东西转换为右值。而且,不,它并没有以任何方式破坏,只是一个转换。(但是转换的目的是允许某些函数“销毁”传递的对象。) - UncleBens
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接