[英]C++11 string assignment operator
看看这段代码:
#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;
}
谢谢大家的快速和有用的答案!
您不应对标准库的移动对象的状态做出具体假设,除非它是合法状态(除非指定了移动赋值运算符或移动构造函数的其他后置条件)。
根据C ++ 11标准的第17.6.5.15段:
可以从(12.8)移动C ++标准库中定义的类型的对象。 可以显式指定或隐式生成移动操作。 除非另有规定,否则此类移动对象应置于有效但未指定的状态。
此外,关于basic_string
类模板的move-assignment运算符的第21.4.2 / 21-23段没有指定关于move-from字符串是否应该保留在一个状态,以便调用它上面的empty()
返回true
。
在这种情况下调用empty()
是合法的,因为它对调用它的string
对象的状态没有任何先决条件; 另一方面,您不能对其返回值应该做出假设。
其他答案指出,通过标准,您不能依赖于将该对象留空的字符串对象的移动操作。
但是,您应该期望比副本更有效。 当然发生的是你的编译器的basic_string<>& operator=(basic_string<>&&)
(字符串'移动赋值')是通过交换两个字符串对象来实现的(这正是标准的建议:“注意:有效的实现是swap(str)。“)。
g ++显然以这种方式实现了字符串移动赋值。
所以你不需要担心效率 - 不应该对字符串进行不必要的复制。 但是,如果您将再次使用该对象,则需要确保在移动后清除从字符串移动的字符串。
除了其他人在此之后关于移动和使用移动物体的说法之外,移动并不完全是你想要做的。 您在概念上想要的是将_longest
的内容分配给longest_phrase
并清除_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());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.