静态演员的描述说
如果 new_type 是右值引用类型,则 static_cast 将表达式的值转换为 xvalue。这种类型的 static_cast 用于在 std::move 中实现移动语义。(C++11 起)
这是否确认以下内容是等价的?
(一个)
X x1;
X x2 = static_cast<X&&>(x1);
(乙)
X x1;
X x2 = std::move(x1);
静态演员的描述说
如果 new_type 是右值引用类型,则 static_cast 将表达式的值转换为 xvalue。这种类型的 static_cast 用于在 std::move 中实现移动语义。(C++11 起)
这是否确认以下内容是等价的?
(一个)
X x1;
X x2 = static_cast<X&&>(x1);
(乙)
X x1;
X x2 = std::move(x1);
是的,有一个非常重要的区别:std::move
记录您想要做什么。此外,演员阵容容易出现诸如忘记&
或错误类型之类的书写错误X
。
可以看出,std::move
输入的内容更少。
在 C++11 中,T&&
是一个右值引用。它们的行为类似于 C++ 98/03 中的左值引用。他们的目标——成为搬家的候选人。在 C++98 中,此构造可以出现在引用折叠中。
std::move
- 将表达式转换为右值。它可能被称为rvalue_cast,但不是。
原则上可以显式转换为类型T&&
。官方标准要花一些钱,但在ISO/IEC 14882:2011草案中是这样的:
5.2.9 静态转换
8)
左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 转换应用于操作数....
从实用的角度来看,使用起来更方便std::move
。
考虑这个例子:
#include <stdio.h>
#include <utility>
class A
{
public:
A () {printf ("A ()" "\n");}
A (const A &) {printf ("A (&)" "\n");}
A (A &&) {printf ("A (&&)" "\n");}
A (const A &&) {printf ("A (const &&)" "\n");}
~ A () {printf ("~ A ()" "\n");}
};
int main ()
{
const A obj;
A obj2 (std::move (obj)); // 1-st approach
A obj3 (static_cast <const A&&> (obj)); // 2-nd approach
}
对我来说,第一种方法是:
static_cast
到const A&&
,还是到A&&
?)std::move
项目中查找)它们不是严格等价的。std::move()
的实施依赖于static_cast
:
template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
它们在必须处理引用崩溃std::move()
的意义上有所不同。(A) 和 (B) 不严格等价的示例:remove_reference
// Set up different behavior for lvalue and rvalue.
class T {};
void func(T&& t) { std::cout << "rvalue captured.\n"; }
void func(T& t) { std::cout << "lvalue captured.\n"; }
// Example:
Using X = T&;
X x1;
X x2 = static_cast<X&&>(x1); // (A) "lvalue captured."
X x3 = std::move(x1); // (B) "rvalue captured."
当 a 是右值时可以使用static_cast<A &&>(a)
,但不应使用std::move(a)
.
当你使用 时A && a = std::move(A())
,你会得到一个悬空引用。
基本思想是不能通过“传递”来进一步延长临时的生命周期:第二个引用,从临时绑定的引用初始化,不会影响它的生命周期。
std::move
的实现有点像
template <typename T>
constexpr decltype(auto) move(T && __t) noexcept // when used in std::move(A()),
// the lifetime of the temporary object is extended by __t
{
return static_cast<typename std::remove_reference<T>::type &&>(__t); // a xvalue returned, no lifetime extension
}
auto && a = std::move(A()); // the anonymous object wiil be destructed right after this line