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;
}
int a = 3;
a
时,它将成为一个左值。即使a
被声明为右值引用,这也是正确的:int &&a = 3;
a
也成为了一个lvalue(基本上是因为它“有一个名字”)。3
或通过复制从函数调用返回的临时值时,唯一合法的转换是到const引用(非const引用不允许绑定到prvalue)。static_cast<const&>
是否真的可以防止函数返回时的隐式移动? - Martin Bastd::move
的行为:如果函数返回类型被定义为左值引用,则在返回之前执行std::move
将不启用移动语义。) - jogojapanT local1; ... T local2 = local1; /*<- 复制*/ ... return local2; /*<- 可能会移动*/
) - Martin Bareturn local2;
可能仍然会触发移动操作,对吗?这种方式如何防止移动操作发生呢? - jogojapanlocal2
阻止了原始对象local1
的移动。我的意思是,如果我处于不希望本地对象被移动的情况下,我可以将"其值"复制到另一个本地对象中并返回该对象。这样原始的本地对象就不会被返回,因此也不会被移动。(是的,我真的无法想象何时会想要这样做。) - Martin Bareturn
时,local1
将会超出作用域,而在此之前,local2
尚未移动,所以确实......没有什么用处。但是再次强调,就像std::move
不能覆盖已声明的返回类型一样,我的建议转换也不能这样做。但我相信std::move
的主要目的是指导编译器选择正确的函数重载(即通常应用于函数参数,而不是在返回语句中)。在这个函数中,建议的转换是一个很好的"反移动"候选项。 - jogojapantemplate<class T>
T& unmove(T&& t)
{
return t;
}
这将改变参数表达式的值类别为lvalue,无论它最初是什么。
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
}
return unmove(local_variable);
- Martin Bareturn unmove(local);
不起作用。这就是我这样阅读的。 - Martin Baenter 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;
}
return std::copy_only(v);
会妨碍编译器执行该操作。 - Xeogetaddrinfo(ip, port, &static_cast<const addrinfo&>(addrinfo{ .ai_family = AF_INET }), &host);
中受益。 - OwnageIsMagic