std::move(*this)是一个很好的模式吗?
Is std::move(*this) a good pattern?
为了使这段带有 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答案中理解的:
std::move(*this)
在语法和概念上是正确的但是,如果
gun
不是所需接口的一部分,则没有理由重载它的lv-ref和rv-ref版本。两个具有不同名称的函数可以完成相同的工作。毕竟,引用限定符在接口级别很重要,这通常只是公共部分。
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
拆分为两个不同名称的函数具有可读性优势,这样做的成本是,嗯......,std::move(*this)
。
编辑2:回想起来,这类似于同一函数const
和无const
过载的C++98情况。在某些情况下,使用 const_cast
(另一种形式的强制转换(来不重复代码并让两个函数具有相同的名称 (https://stackoverflow.com/a/124209/225186( 是有意义的。...尽管在更复杂的情况下,使用辅助私有函数来委托接口函数的正确行为是有意义的。
是的,无论如何调用成员函数,*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
与任何参考函数参数没有什么不同。
- 在 C++11 中利用 int*_t、int_fast*_t 和 int_least*_t 之间的差异的一个很好的例子是
- 对于短字符串来说,这是一个很好的哈希函数吗?
- 是否有一个很好的方法可以在C 11中打印出像JSON一样的Trie结构(仅迭代解决方案)的扁平命名空间
- 为什么这会在Java中给我一个ClasscastException,而它在C 中效果很好
- 将libstdc 静态链接起来是一个很好的做法
- 有一个标准的容器可以很好地回收吗
- 用"gcc -c"通关很好地编译一个C++程序。为什么?
- 对于这个特定用例来说,一个很好的排序算法
- 一个很好的支持 c++ 联合的替代方案
- 有没有一个很好的通用方法来用ruby包装swig生成的类
- boost asio和c++11是一个很好的匹配
- 这是"mutable" C++的一个很好的用例吗?
- 一个很好的向量散列函数
- 当我为调试Lua编译程序时,运行得很好,但为什么我要为发布版编译它,我得到了一个c0000005错误
- 将类的std::vector作为同一类的属性是一个很好的设计选择
- 一个很好的例子说明了如何使函数primitve param const导致编译器优化
- 一个很好的算法来获得元素的闲置组合
- std::move(*this)是一个很好的模式吗?
- Qt:在c++类中有一个未声明为指针的小部件字段是很好的
- 如果我把这些都放到另一个函数里,是不是很好