为什么 std::move() 中的 static_cast 会擦除参数的值?

问题描述

我的问题包含两部分:

  1. 函数 static_cast<Т>(arg) 会改变 arg 的内部吗?显然不是,根据这样的代码

    float i1 = 11.5;
    int x = static_cast<int>(i1);
    std::cout << i1<<std::endl;   //11.5
    std::cout << x<<std::endl;    //11
    
  2. 为什么会有这样的代码

    std::string s1 = "123";
    std::string s2 = std::move(s1);
    std::cout << s1 << std::endl;  //empty
    std::cout << s2 << std::endl;  //123
    

    其中 std::move() 仅使用 static_cast 到 r 值:

    template<typename _Tp>
    constexpr typename std::remove_reference<_Tp>::type&&
    move(_Tp&& __t) noexcept
    { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
    

    使 s1 为空字符串?

我猜,是因为在s2 =之后使用了字符串的移动构造函数。它必须通过将字符串对象中的所有数据等于 nullptr 或 0 来擦除初始字符串。而 std::move() 本身仅返回右值。正确吗?

我知道我的问题与 static_cast to r-value references and std::move change their argument in an initialization 类似,但我没有找到明确的解释。

解决方法

在阅读您的问题时,我有一种感觉,您已经了解正在发生的事情,但仍希望确认

我猜,这是因为在 s2 = 之后使用了 string 的移动构造函数。它必须通过等于 nullptr 或 0 string 对象中的所有数据来擦除初始字符串。而 std::move() 本身仅返回右值。

正确吗?

是的,你没看错。基本上就是这样。

std::move 不会移动并且不会改变对象“自身”的任何状态。 它只是将给定对象的类型转换为右值引用。

它是 std::basic_string 的构造函数,它消除了示例中的 s1

cppreference 中,它为您简要介绍了它的作用:

... 使用移动语义构造具有 other 内容的字符串。 other 处于有效但未指定的状态。

尝试编写这样的示例代码来证明您的观点:

std::string s = "Hello World";
(void)std::move(s); // (void) is there to discard the warning message.
std::cout << s;

您可以看到 s 完全没有改变。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...