以下代码:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1 = "hello";
string s2 = "my";
string s3 = "world";
string s4;
s4 = move(s1) + move(s2) + move(s3);
cout << "s4(" << s4 << ") = s1(" << s1 << ") + s2(" << s2 << ") + s3(" << s3 << ")"<< endl;
}
给出以下输出:
s4(hellomyworld) = s1() + s2(my) + s3(world)
你能解释一下发生了什么吗? (使用XCode 4.6.1测试)
编辑:
我希望看到:
s4(hellomyworld) = s1() + s2() + s3()
答案 0 :(得分:4)
我假设你期待s4(hellomyworld) = s1() + s2() + s3()
。
首先,运动将源对象保留为“具有未指定值的有效状态”([C++11: 21.4.2/2]
) - 也就是说,您不能对移动后字符串的值进行任何声明从它。
其次,std::move
是用词不当,因为它实际上并没有移动任何东西。通过交换周围的事物来实现移动,并且不能保证你的string operator+
做任何类似的事情(参见jmihalicza对样本实现的回答);所有std::move
都会获得一个可以移动 的右值引用。
[C++11: 21.4.6.3/1]
说std::basic_string& assign(basic_string&& str) noexcept
(这是你真正调用的函数,当你按照operator+
中的所有面包屑执行时)“有效的实现是swap(str)
“,但这并不意味着交换发生。
答案 1 :(得分:1)
s4 = move(s1) + move(s2) + move(s3)
实际上是operator=(s4, operator+(operator+(move(s1), move(s2)), move(s3));
operator+
的实现不需要修改其rvalue参数,但是是允许的。据推测,实现是这样的:
string operator+(string&& left, string&& right)
{
string result(left);
return result += right;
}
只读权利。
答案 2 :(得分:0)
template<class _CharT, class _Traits, class _Allocator>
_LIBCPP_INLINE_VISIBILITY inline
basic_string<_CharT, _Traits, _Allocator>
operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs)
{
return _VSTD::move(__lhs.append(__rhs));
}
似乎在连接期间__rhs
保持不变。在s1累积所有字符串之后,s4的移动分配清空了s1。