C++ std::move(*这)是一种好模式吗?
为了使带有C++11引用限定符的代码按预期工作,我必须引入一个听起来不正确的C++ std::move(*这)是一种好模式吗?,c++,c++11,this,move-semantics,lvalue,C++,C++11,This,Move Semantics,Lvalue,为了使带有C++11引用限定符的代码按预期工作,我必须引入一个听起来不正确的std::move(*this) #include<iostream> struct A{ void gun() const&{std::cout << "gun const&" << std::endl;} void gun() &&{std::cout << "gun&&&qu
std::move(*this)
#include<iostream>
struct A{
void gun() const&{std::cout << "gun const&" << std::endl;}
void gun() &&{std::cout << "gun&&" << std::endl;}
void fun() const&{gun();}
void fun() &&{std::move(*this).gun();} // <-- is this correct? or is there a better option
};
int main(){
A a; a.fun(); // prints gun const&
A().fun(); // prints gun&&
}
但是同样,如果gun
是(通用)接口的一部分,那么std::move(*这个)
是必要的,但只有在那时。而且,即使gun
不是接口的一部分,也不将函数gun
拆分为两个不同名称的函数具有可读性优势,而且这样做的成本是,std::move(*this)
编辑2:回想起来,这类似于C++98中相同函数的const
和no-const
重载的情况。在某些情况下,使用const_cast
(cast的另一种形式)不重复代码并使两个函数具有相同的名称()是有意义的。
... 尽管在更复杂的情况下,使用辅助私有函数来委托接口函数的正确行为是有意义的。是的,
*无论如何调用成员函数,此
始终是左值,因此如果希望编译器将其视为右值,您需要使用std::move
或等效工具。考虑到这一类,它必须是:
struct A {
void gun() &; // leaves object usable
void gun() &&; // makes object unusable
void fun() && {
gun();
gun();
}
};
如果将*此
设为右值,则表明fun
对gun
的第一次调用可能会导致对象无法使用。然后,第二次呼叫将失败,可能会严重失败。这不是应该暗中发生的事情
这也是为什么在
void f(T&&T)
中,T
是左值的原因。在这方面,*此
与任何参考函数参数没有区别。是的,我理解。那么std::move(*这个)
是使用调用链中所有&&
函数的方法吗?(我澄清了上面的真实问题)@alfC是的,就像其他函数参数一样。调用者指定可以安全地从中移动对象,但被调用函数本身也需要这样做,因为编译器无法自动解决这个问题。(当然,由于这个是您自己的类类型,您也可以采用不同的方法:转发到可以对左值调用的私有破坏性成员函数。由于它是私有的,外部用户不能意外调用它。)我不理解另一种方法,使用私有破坏性(?)为了说明,示例中的第二个调用可能应该是std::move(*this).gun()
@alfC任何void gun()&&
可以做的事,void gun()
可以做的事。因此,如果您想调用void gun()&&
版本,您可以做的是实现void gunRvalue()
,它是私有的
,除非另有规定,否则通常不安全地调用左值。你可以从一个public
函数调用它,比如:void gun()&&{gunRvalue()}
,任何你想调用void gun()&&&
版本的东西,都可以直接调用gunRvalue()
。如果你不想使用std::move
,那么static\u cast(*this.gun()
?@yohjp,或者std::forward(*this).gun()
,我建议创建一个名为rvalue()
的成员函数,将*this
作为rvalue返回。然后您可以调用this->rvalue()->…
@Mehrdad,它是这样编写的函数吗auto rvalue()->decltype(std::move(*this)){return std::move(*this);}
?
struct A {
void gun() &; // leaves object usable
void gun() &&; // makes object unusable
void fun() && {
gun();
gun();
}
};