alf*_*lfC 31 c++ this lvalue move-semantics c++11
为了使这个代码与C++ 11引用限定符按预期工作,我必须引入一个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&&
}
Run Code Online (Sandbox Code Playgroud)
有些事情听起来不对劲.有std::move必要吗?这是推荐使用吗?目前,如果我不使用它,我会遇到gun const&两种情况,这不是预期的结果.
(似乎*this总是隐式和左值引用,这是有道理的,但然后是逃避使用的唯一方法move)
用clang 3.4和测试gcc 4.8.3.
编辑:这是我从@hvd回答中理解的:
1)std::move(*this)在语法和概念上是正确的
2)但是,如果gun不是所需接口的一部分,则没有理由重载它的lv-ref和rv-ref版本.两个具有不同名称的函数可以完成相同的工作.所有ref-qualifiers在接口级别都很重要,这通常只是公共部分.
struct A{
private:
void gun() const{std::cout << "gun const&" << std::endl;}
void gun_rv(){std::cout << "gun called from fun&&" << std::endl;}
public:
void fun() const&{gun();}
void fun() &&{gun_rv();} // no need for `std::move(*this)`.
};
Run Code Online (Sandbox Code Playgroud)
但同样,如果gun是(通用)接口的一部分,那么std::move(*this)是必要的,但只有这样.而且,即使gun是在不分裂不是该函数的接口有可读性的优点的一部分gun作为两个不同的名称,功能和这个成本,那么...... std::move(*this).
编辑2:回想起来,这类似于相同功能的C++ 98情况const和没有const重载.在某些情况下,使用const_cast(另一种形式的强制转换)不重复代码并使两个函数具有相同的名称是有意义的...
编辑3:... /sf/answers/8694661/
小智 21
是的,*this总是一个左值,无论如何调用成员函数,因此如果您希望编译器将其视为右值,则需要使用std::move或等效.它必须是,考虑到这个类:
struct A {
void gun() &; // leaves object usable
void gun() &&; // makes object unusable
void fun() && {
gun();
gun();
}
};
Run Code Online (Sandbox Code Playgroud)
制作*this一个rvalue会表明fun第一次调用gun会使对象无法使用.然后第二次调用会失败,可能很糟糕.这不是隐含的事情.
这是一样的道理,为什么里面void f(T&& t),t是一个左值.在这方面,*this与任何参考函数参数没有区别.