给定一个程序:
#include <iostream>
#include <vector>
using namespace std;
struct Vec {
Vec() = default;
Vec(const Vec& vec)
: v_(vec.v_)
{
cout << "copy Vec" << endl;
}
Vec(Vec&& vec)
: v_(std::move(vec.v_))
{
cout << "move Vec" << endl;
}
vector<double> v_{};
};
struct T1 {
Vec Value;
};
struct T2 {
T2(const T1& t1)
: Value(std::move(t1.Value))
{
}
Vec Value;
};
struct T3 {
T3(T1&& t1)
: Value(std::move(t1.Value))
{
}
Vec Value;
};
int main() {
T1 t1;
T2 t2{ t1 };
T3 t3{ std::move(t1) };
return 0;
}
输出:
copy Vec
move Vec
在这两种情况下,我std::move
正在t1.Value
到Vec
ctor。
是否有可能在Clang(或其他编译器)中启用某些警告,因此它警告我移动实际上调用了复制构造函数?
(例如,当我从函数返回std::unique_ptr
std::move(result)
时,Clang已经可以警告性能问题了。)
答案 0 :(得分:1)
是否有可能在Clang(或其他编译器)中启用某些警告,因此它警告我移动实际上调用了复制构造函数?
移动过程与专门调用std::move
无关。这只是演员。调用移动构造函数/赋值运算符时会发生移动。移动可以在不调用std::move
的情况下发生(例如,编译器警告您的情况),并且正如您所看到的那样,即使您使用std::move
也不会发生移动。
您无法从const
引用移动,因为......它是 const
。运动具有破坏性,因此需要能够修改物体。哪个const
不允许。
运动最终是一种优化的复制操作。因此,执行复制而不是移动通常是可以的,特别是如果类型没有移动构造函数。
如果您愿意,您可以编写自己的std::move
版static_assert
T
不是const
:
template< class T >
constexpr typename std::remove_reference<T>::type&& my_move( T&& t )
{
static_assert(!std::is_const<T>::value, "Cannot move from a const reference");
return static_cast<typename std::remove_reference<T>::type&&>(t);
}