我的问题包含两部分:
函数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
删除实体中的所有引用,并通过添加&;最后在CCD_ 21中发送给它。
任何引用都只是它所引用实体的另一个名称,我们可以通过该引用来更改该实体。在某些近似中,引用被当作它所引用的对象来处理
因此,std::move()
返回一个对右值实体的新引用,因此根据上面列出的推理,这个右值引用被感知为右值实体。所以std::move()的结果可能会作为右值参数输入到适当的构造函数或函数中。因此,为了改变引用所指实体的引用能力,我们可以改变初始实体,即使它是左值(设置为零ptr等)