首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::move和std::复制相同吗?

std::move和std::复制相同吗?
EN

Stack Overflow用户
提问于 2014-10-17 20:29:08
回答 2查看 7.8K关注 0票数 10

我试着做这样的事情:

代码语言:javascript
复制
std::copy(std::make_move_iterator(s1.begin()), std::make_move_iterator(s1.end()), 
          std::make_move_iterator(s2.begin()));

并得到了以下错误:

代码语言:javascript
复制
error: using xvalue (rvalue reference) as lvalue
        *__result = std::move(*__first);

我觉得很困惑。如果使用std::move,也会发生同样的情况。GCC内部似乎使用了一个名为std::__copy_move_a的函数,它可以移动而不是复制。您使用std::copy还是std::move是否重要?

代码语言:javascript
复制
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstring>

struct Test
{
    typedef std::string::value_type value_type;
    std::string data;

    Test()
    {
    }

    Test(const char* data)
        : data(data)
    {
    }

    ~Test()
    {
    }

    Test(const Test& other)
        : data(other.data)
    {
        std::cout << "Copy constructor.\n";
    }

    Test& operator=(const Test& other)
    {
        data = other.data;
        std::cout << "Copy assignment operator.\n";
        return *this;
    }

    Test(Test&& other)
        : data(std::move(other.data))
    {
        std::cout << "Move constructor.\n";
    }

    decltype(data.begin()) begin()
    {
        return data.begin();
    }

    decltype(data.end()) end()
    {
        return data.end();
    }

    void push_back( std::string::value_type ch )
    {
        data.push_back(ch);
    }
};

int main()
{
    Test s1("test");
    Test s2("four");
    std::copy(std::make_move_iterator(s1.begin()), std::make_move_iterator(s1.end()), 
              std::make_move_iterator(s2.begin()));
    std::cout << s2.data;
}
EN

回答 2

Stack Overflow用户

发布于 2014-10-17 20:42:34

std::move(a, b, c);在语义上与

代码语言:javascript
复制
std::copy(std::make_move_iterator(a),
          std::make_move_iterator(b),
          c);

您使用它们的努力都失败了,因为第三个参数--输出迭代器--不应该是移动迭代器。您正在存储到第三个迭代器中,而不是从它移动。两者都有

代码语言:javascript
复制
std::copy(std::make_move_iterator(s1.begin()),
          std::make_move_iterator(s1.end()),
          s2.begin());

代码语言:javascript
复制
std::move(s1.begin(), s1.end(), s2.begin());

应该做你想做的事。

票数 22
EN

Stack Overflow用户

发布于 2014-10-17 20:37:06

如果可能的话,std::move会移动元素,否则就复制元素。std::copy总是复制。

libstdc++的copy_move_a还接受一个模板参数_IsMove,以及迭代器类型,它将委托给一个__copy_move类模板,该模板部分地专门针对不同的迭代器类别,但最重要的是:是否为move

代码语言:javascript
复制
#if __cplusplus >= 201103L
  template<typename _Category>
    struct __copy_move<true, false, _Category>
    // first specialized template argument is whether to move
    {
      template<typename _II, typename _OI>
        static _OI
        __copy_m(_II __first, _II __last, _OI __result)
        {
      for (; __first != __last; ++__result, ++__first)
        *__result = std::move(*__first); // That may be your line
      return __result;
    }
    };
#endif

您的代码无法编译是因为一个完全不同的原因:第二个范围是通过move_iterator提供的。如果取消对它们的引用,它们会向对象返回一个rvalue引用--而且您不能将某些东西分配给标量类型的xvalue。

代码语言:javascript
复制
int i;
std::move(i) = 7; // "expression not assignable" -- basically what your code does

std::move隐式地包含在*__result中,并且属于相同的值类别,即xvalue。

以你为例,

代码语言:javascript
复制
std::copy(std::make_move_iterator(s1.begin()), std::make_move_iterator(s1.end()),
          s2.begin());

应该能正常工作。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26432990

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档