连接两个移动的字符串

时间:2013-05-25 08:14:06

标签: c++ c++11 move-semantics

以下代码:

#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()

3 个答案:

答案 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。