1

下面的代码:

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

4

3 回答 3

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)

于 2013-05-25T08:25:59.657 回答
1

s4 = move(s1) + move(s2) + move(s3)实际上是operator=(s4, operator+(operator+(move(s1), move(s2)), move(s3)); 的实现operator+不需要修改它的右值参数,但是是允许的。大概实现是这样的:

string operator+(string&& left, string&& right)
{
   string result(left);
   return result += right;
}

仅读取正确的位置。

于 2013-05-25T08:22:30.517 回答
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));
}

所以似乎在串联期间__rhss 保持不变。在 s1 处累积所有字符串后,s4 的移动分配清空 s1。

于 2013-05-25T08:41:07.703 回答