首页 >后端开发 >C++ >当右值引用应该只绑定到右值时,std::move() 如何绑定到左值?

当右值引用应该只绑定到右值时,std::move() 如何绑定到左值?

DDD
DDD原创
2024-11-14 10:46:011038浏览

How does std::move() bind to lvalues when rvalue references are supposed to only bind to rvalues?

揭开 std::move 转换魔法的神秘面纱

当调用 std::move() 时,令人费解的是观察到引用的右值参数可以绑定到左值,通常限制左值附加到右值引用。深入研究 std::move() 的实现揭示了这个明显悖论的关键。

剖析 std::move() 实现

从精炼的开始std::move() 的版本:

template <typename T>
typename remove_reference<T>::type&& move(T&& arg) {
  return static_cast<typename remove_reference<T>::type&&>(arg);
}

情况 1:使用右值调用 move()

当 move() 与右值一起使用时,例如临时对象:

Object a = std::move(Object()); // Object() is temporary, hence prvalue

生成的模板实例化为:

remove_reference<Object>::type&& move(Object&& arg) {
  return static_cast<remove_reference<Object>::type&&>(arg);
}

由于remove_reference将T&转换为T或T&&转换为T,并且Object是一个普通值,所以最终的函数形态变为:

Object&& move(Object&& arg) {
  return static_cast<Object&&>(arg);
}

强制转换至关重要,因为命名的右值引用被视为左值。

情况 2:使用左值调用 move()

当使用左值调用 move() 时:

Object a; // a is an lvalue
Object b = std::move(a);

生成的 move() 实例化为:

remove_reference<Object&>::type&& move(Object& && arg) {
  return static_cast<remove_reference<Object&>::type&&>(arg);
}

再次,remove_reference 将 Object& 转换为 Object,产生:

Object&& move(Object& && arg) {
  return static_cast<Object&&>(arg);
}

引用折叠的本质

理解 Object& && 及其绑定左值的能力是解开谜团的关键。 C 11 引入了引用折叠的特殊规则,其中规定:

Object & && = Object &
Object & &&& = Object &
Object && & = Object &
Object && &&& = Object &&

因此,Object& && 实际上转换为 Object&,一个可以轻松绑定到左值的典型左值引用。

结果函数

使用这些规则,最终函数将变为:

Object&& move(Object& arg) {
  return static_cast<Object&&>(arg);
}

镜像右值的实例化,它将其参数转换为右值引用,从而确保统一的行为.

remove_reference 的重要性

当检查替代函数时,remove_reference 的目的变得显而易见:

template <typename T>
T&& wanna_be_move(T&& arg) {
  return static_cast<T&&>(arg);
}

当用左值实例化时:

Object& && wanna_be_move(Object& && arg) {
  return static_cast<Object& &&&>(arg);
}

应用引用折叠规则揭示了一个不可用的类似移动的函数,为左值参数返回左值。罪魁祸首是缺少remove_reference,它阻碍了正确转换为右值引用。

以上是当右值引用应该只绑定到右值时,std::move() 如何绑定到左值?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn