2

看看这段代码:

#include <iostream>
#include <algorithm>
#include <fstream>
#include <iterator>

using namespace std;

int main()
{
ifstream text("text.txt");

istreambuf_iterator<char> iis(text);
string longest_phrase, _longest;

while (iis != istreambuf_iterator<char>()) {
    if ( *iis != '.' ) {
        _longest.push_back(*iis);
        ++iis;
        continue;
    }
    if ( _longest.size() > longest_phrase.size() )
        longest_phrase = move(_longest); //I want to move the data of _longest to longest_phrase. Just move! Not to copy!
    cout << _longest.empty(); //why _longest is not empty??
            //_longest.clear();
    ++iis;
}
text.close();
longest_phrase.push_back('.');
cout << "longest phrase is " << longest_phrase;
return 0;
}

此代码搜索文件中最长的短语。那么为什么从左值到右值的转换不起作用呢?

编辑:这就是为什么我认为它不起作用:

class Vector {
public:
    Vector(vector<int> &&v): vec( move(v) ) {}
    vector<int> vec;
};

int main()
{
    vector<int> ints(50, 44);
    Vector obj( move(ints) );
    cout << ints.empty();
    return 0;
}

谢谢大家的快速和有用的答案!

4

3 回答 3

9

您不应该对标准库的已移动对象的状态做出具体假设,除非它是合法状态(除非指定了移动赋值运算符或移动构造函数的进一步后置条件)。

根据 C++11 标准的第 17.6.5.15 段:

C++ 标准库中定义的类型的对象可以从 (12.8) 中移出。移动操作可以显式指定或隐式生成。除非另有说明,否则此类移出的对象应置于有效但未指定的状态。

此外,关于类模板的移动赋值运算符的第 21.4.2/21-23 段basic_string没有指定任何关于移动的字符串是否应保持在调用empty()它返回的状态true

在这种情况下调用是合法的,因为它对调用它的对象empty()的状态没有任何先决条件;string另一方面,您不能对其返回值做出假设。

于 2013-05-10T09:43:43.980 回答
3

其他答案指出,按照标准,您不能依赖字符串对象的移动操作而使该对象为空。

但是,您应该期望正在发生比副本更有效的事情。肯定发生的是,您的编译器basic_string<>& operator=(basic_string<>&&)(字符串“移动赋值”)是通过交换两个字符串对象来实现的(这正是标准的建议:“注意:有效的实现是 swap(str)。”)。

g++ 显然以这种方式实现了字符串移动赋值。

所以你不需要担心效率——不应该有不必要的字符串复制。但是,如果您要再使用该对象,您确实需要确保在移动后清除已移动的 from 字符串。

于 2013-05-10T10:52:44.580 回答
1

除了其他人所说的移动和使用移动的对象之后,移动并不是你想要在这里做的。您在概念上想要的是分配_longesttolongest_phrase和 clear的内容_longest。您试图避免复制和重新分配是正确的,但您可以通过交换轻松实现:

 if ( _longest.size() > longest_phrase.size() )
 {
    longest_phrase.clear(); // don't need the old content any more
    longest_phrase.swap(_longest); //move the data of _longest to longest_phrase
 }
 assert(_longest.empty());  
于 2013-05-10T10:15:13.030 回答