代码之家  ›  专栏  ›  技术社区  ›  Mansoor

在std::move之后使用std::字符串是否有效?[副本]

  •  0
  • Mansoor  · 技术社区  · 4 年前

    第二个参数是否安全且定义良好 std::getline(std::istream&, std::string&) 是左值,指从 std::string ,如果是的话,那么这个字符串是否从其moved from状态中恢复,以及 pop_back()

    简单地说,写一个字符串就行了 getline() 对那个字符串有等价的语义吗?

    或者更具体地说,下面的代码片段(有点做作)是否定义良好且正确?

    std::ifstream f("foo.txt");
    
    std::vector<std::string> lines;
    
    for (std::string s; std::getline(f, s); lines.push_back(std::move(s)))
            if (!s.empty() && s.back() == '\r')
                    s.pop_back();
    

    优化( -march=native -O3 )此代码段的生成 g++ clang++ 似乎工作如预期,但这当然不能保证。

    我想知道这是否仅仅依赖于根据 getline() 在C++ 11标准中,或者如果不是,如果它是由标准的后版本定义的,或者如果不是,则至少它是由任何/所有主要实现(G++、Clang ++、Visual C++、英特尔C++编译器)明确定义的。

    注:这是 重复前面的问题,询问是否可以安全地分配给moved from对象(是的,如果它是普通类型或STL类型),因为 getline() 不是赋值运算符。

    0 回复  |  直到 7 年前
        1
  •  9
  •   Howard Hinnant    7 年前

    您的代码是安全的,但这仅仅是因为您正在检查 getline 成功地将某些内容存储在 s . 如果哨兵在内部 getline公司 初始化失败,则不会分配任何内容 它将处于有效但未指明的状态。只要 getline公司 s码 到一个已知的状态,你是好的。

    第一件事 getline公司 s码 到零大小(已知状态)。

    更多细节见GManNickG的评论。

        2
  •  5
  •   Rakete1111    7 年前

    第二个参数是否安全且定义良好 std::getline(std::istream&, std::string&) 是左值,指从 std::string

    对。尽管它是从字符串中移出的,但是根据 [string.cons]p2 :

    [...]. 在第二种形式中, str 处于具有未指定值的有效状态。

    std::getline 因为标准上说 [string.io]p1 那个 str.erase() 在字符串上调用,从而清空它:

    […]个电话 删除str.erase() [...]

    (如果流是有效的,但我会假设这是在您的情况下)。

    不管字符串的未指定状态是什么,它都会在 标准::getline ,所以它处于什么状态并不重要。

        3
  •  1
  •   Community CDub    5 年前

    移动赋值或移动计算器应始终使移动对象保持有效状态。

    std::move 它是一个有效但未指定的字符串。来自libc++的源代码:

    // __str is a valid, but unspecified string. 
    basic_string(basic_string&& __str) noexcept
      : _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator()))
    

    getline() 只向字符串追加字符,只要成功,输出就会如预期的那样。从 cplusplus.com :

    请注意,调用之前str中的任何内容都被新提取的序列替换。

    每个提取的字符都会附加到字符串中,就好像调用了其成员push\u back一样。