std::move
可用于在不允许隐式移动时显式允许移动语义(例如从函数返回本地对象时为often)。
现在,我想知道(尤其是在本地返回和隐式移动的情况下),如果存在{em}的倒数这样的事情阻止移动对象(但仍允许复制)。
这是否有意义?
答案 0 :(得分:2)
std::move
将左值转换为右值,它基本上由static_cast
完成。与我所能想到的最接近的是这两种类型的演员阵容:
static_cast<T &>(/*rvalue-expression*/)
static_cast<const T&>(/*rvalue-expression*/)
以下是一个例子:
#include <iostream>
void f(const int &)
{ std::cout << "const-lval-ref" << std::endl; }
void f(int &&)
{ std::cout << "rval-ref" << std::endl; }
int main()
{
f(static_cast<const int &>(3));
return 0;
}
将prvalue 3
投射到const int &
可确保选择f
的左值超载。
在大多数情况下,只需指定一个变量,就可以自动进行右值左值修改:
int a = 3;
在此行之后使用a
时,它将是左值。即使将a
声明为右值引用,也是如此:
int &&a = 3;
在这里,a
也变成左值(基本上因为它“有一个名字”)。
我可以想象一个显式演员有任何相关效果的唯一情况是我上面的第一个例子。在那里,当处理像3
这样的prvalues或者通过副本从函数调用返回的临时值时,唯一合法的转换是const-reference(不允许非const引用绑定到prvalue)。
答案 1 :(得分:0)
防止对象移动的解决方案是使对象的移动构造函数为私有,这样对象就无法移动但可以被复制。
移动示例:
enter code here
#include <iostream>
class A {
public:
std::string s;
A() : s("test") {}
A(const A& o) : s(o.s) { std::cout << "move failed!\n";}
A(A&& o) : s(std::move(o.s)) { std::cout << "move was succesfull!\n"; }
};
int main(int argc, const char * argv[])
{
A firsObject;
A secondObject = std::move(firsObject);
return 0;
}
禁用移动的示例:
#include <iostream>
class A {
public:
std::string s;
A() : s("test") {}
A(const A& o) : s(o.s) { std::cout << "move failed!\n";}
private:
A(A&& o) : s(std::move(o.s)) { std::cout << "move was succesfull!\n"; }
};
int main(int argc, const char * argv[])
{
A firsObject;
A secondObject = std::move(firsObject);
return 0;
}
答案 2 :(得分:0)
template<class T>
T& unmove(T&& t)
{
return t;
}
这会将参数表达式的值类别更改为左值,无论它最初是什么。
void f(const int&); // copy version
void f(int&&); // move version
int main()
{
int i = ...;
f(42); // calls move version
f(move(i)); // calls move version
f(i); // calls copy version
f(unmove(42)); // calls copy version
f(unmove(move(i))); // calls copy version
f(unmove(i)); // calls copy version
}