【问题标题】:Concatenating two moved strings连接两个移动的字符串
【发布时间】:2013-05-20 19:22:29
【问题描述】:

以下代码:

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

【问题讨论】:

  • 请习惯于描述您期望发生的事情。您的理解可能与我们的理解不同(事实上,因为您在这里提出问题是为了解决您的困惑,可能不是!)跨度>

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


【解决方案1】:

我猜你期待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&amp; assign(basic_string&amp;&amp; str) noexcept(当您关注operator+ 中的所有面包屑时,您真正调用的函数)“有效的实现是swap(str)”,但这并不意味着交换必须发生。

【讨论】:

    【解决方案2】:

    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;
    }
    

    其中仅读取权限。

    【讨论】:

    • 如果要返回引用,为什么要创建一个临时的result 变量? (请注意,该标准不会在那里返回参考)
    【解决方案3】:
    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。

    【讨论】:

      猜你喜欢
      • 2020-09-25
      • 2013-11-05
      • 1970-01-01
      • 2011-08-29
      • 2020-08-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多