std::move和std::copy是否相同
Are std::move and std::copy identical?
我试着做一些类似的事情:
std::copy(std::make_move_iterator(s1.begin()), std::make_move_iterator(s1.end()),
std::make_move_iterator(s2.begin()));
得到了这个错误:
error: using xvalue (rvalue reference) as lvalue
*__result = std::move(*__first);
这似乎让我感到困惑。如果你使用std::move
,同样的事情也会发生。GCC内部似乎使用了一个名为std::__copy_move_a
的函数,该函数用于移动而非复制。使用std::copy
还是std::move
有关系吗?
#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;
}
std::move(a, b, c);
在语义上与相同
std::copy(std::make_move_iterator(a),
std::make_move_iterator(b),
c);
您使用它们的努力都失败了,因为第三个参数-输出迭代器-应该而不是是移动迭代器。您正在存储到第三个迭代器中,而不是从中移动
std::copy(std::make_move_iterator(s1.begin()),
std::make_move_iterator(s1.end()),
s2.begin());
和
std::move(s1.begin(), s1.end(), s2.begin());
应该做你想做的事。
std::move
尽可能移动元素,否则进行复制。std::copy
将始终复制。
libstdc++的copy_move_a
还采用了一个模板参数_IsMove
。这以及迭代器类型,它委托给一个__copy_move
类模板,该模板部分专门用于不同的迭代器类别等,但最重要的是:是否委托给move
。其中一个专业是
#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
s给出的。如果您取消引用它们,它们将返回对对象的右值引用,并且您不能为标量类型的xvalue赋值。
int i;
std::move(i) = 7; // "expression not assignable" -- basically what your code does
std::move
隐含地包括在*__result
中,并且具有相同的值类别,即x值。
举个例子,
std::copy(std::make_move_iterator(s1.begin()), std::make_move_iterator(s1.end()),
s2.begin());
应该可以正常工作。
相关文章:
- 检查 std::shared_ptr<> 的当前底层类型是否为 T
- 关于std::move的使用,是否有编译警告
- 通过网络、跨平台传递std::变体是否安全
- 是否有类似std::lower_bound的函数,而不需要排序/分区输入
- std::vector::迭代器是否可以合法地作为指针
- MESI协议和std::atomic-它是否确保所有写入立即对其他线程可见?
- 是否将std::packaged_task添加到现有线程
- C++中是否存在 std::conditional 的懒惰等价物?
- 检查某些类型是否是模板类 std::optional 的实例化
- 如何检查两个 std::向量在小于 O(n) 的时间复杂度内是否相等
- 在C++中,使用带有 std::optional 参数的函数<T>来表示可选参数是否有意义?
- C++标准是否允许<double>在没有开销的情况下实现 std::可选
- '[](std::list& list)<int>{return std::move(list)}(list)' 是否保证将 'list' 留空?
- "std::list::splice(std::const_iterator pos, std::list&& other)"是否保证将"其他"留空?
- 为什么程序员同时使用 std::bad_alloc 和 std::exception.是否 std::例外 仅是不够的
- glibcxx STL 在实现 std::valarray::sum() 时是否不正确?
- 在 C++20 中是否不再允许在 std 中对程序定义类型的函数模板进行专用化?
- 将 std::map::emplace 与返回 shared_ptr 的函数一起使用是否正确?
- "using namespace std;"是否免于过多代码规则?
- GCC 或 Clang '-std=' 是否有任何"moving target"别名值,表示"use the latest standard"?