为了使这段代码与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&&
}
有些事情听起来不对。 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)`.
};
但同样,如果gun
是(通用)接口的一部分,那么std::move(*this)
是必要的,但只有这样。而且,即使gun
不是界面的一部分,在不将功能gun
拆分为两个不同命名的函数时也具有可读性优势,而且成本也很好...... {{1} }。
EDIT 2 :回想起来,这类似于同一函数的std::move(*this)
和无 - const
重载的C ++ 98案例。在某些情况中,使用const
(另一种形式的强制转换)来重复代码并使两个函数具有相同的名称是有意义的...
编辑3 :... https://stackoverflow.com/a/124209/225186
答案 0 :(得分:19)
是的,*this
始终是左值,无论如何调用成员函数,因此如果您希望编译器将其视为右值,则需要使用std::move
或等效函数。它必须是,考虑到这个类:
struct A {
void gun() &; // leaves object usable
void gun() &&; // makes object unusable
void fun() && {
gun();
gun();
}
};
将*this
设为左值会表明fun
第一次调用gun
会导致对象无法使用。然后第二次调用会失败,可能很糟糕。这不是隐含的事情。
这就是为什么void f(T&& t)
内t
是左值的原因。在这方面,*this
与任何参考函数参数没有区别。