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



我的问题包含两部分:

函数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
  • 为什么这样的代码:

    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来擦除初始字符串。而CCD_ 8本身只是返回右值。这是正确的吗?

    我知道我的问题与static_cast到r-value引用和std::move在初始化中更改它们的参数类似,但我还没有找到明确的解释。

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

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

    这是正确的吗?

    是的,你说得对。这基本上就是正在发生的事情。

    CCD_ 13不移动并且不改变对象"em"的任何状态;"其本身"。它只是将给定对象的类型强制转换为右值引用。

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

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

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

    试着写一个这样的示例代码来证明你的观点:

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

    您可以看到s根本没有更改。

    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()返回对右值实体的新引用(右值引用),即使初始实体是左值。它使用通用引用Tp&&作为输入参数,可以引用左值或右值表达式,type_traits函数std::remove_reference删除实体中的所有引用,并通过添加&amp;最后在CCD_ 21中发送给它。

    任何引用都只是它所引用实体的另一个名称,我们可以通过该引用来更改该实体。在某些近似中,引用被当作它所引用的对象来处理

    因此,std::move()返回一个对右值实体的新引用,因此根据上面列出的推理,这个右值引用被感知为右值实体。所以std::move()的结果可能会作为右值参数输入到适当的构造函数或函数中。因此,为了改变引用所指实体的引用能力,我们可以改变初始实体,即使它是左值(设置为零ptr等)

    最新更新