简体   繁体   中英

C++11 string assignment operator

Look at this code:

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

This code searches for the longest phrase in file. So why the conversion from lvalue to rvalue doesnt work?

Edit: That's why I thought that it did not work:

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

Thank you all for the quick and helpful answers!

You should not make concrete assumptions on the state of a moved-from object of the standard library, other than the fact that it is a legal state (unless further post-conditions of the move-assignment operator or move constructor are specified).

Per paragraph 17.6.5.15 of the C++11 Standard:

Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

Moreover, paragraphs 21.4.2/21-23 about the move-assignment operator of the basic_string class template do not specify anything about whether the moved-from string shall be left in a state such that invoking empty() on it returns true .

Calling empty() is legal in this case, since it does not have any pre-conditions on the state of the string object it is invoked on; on the other hand, you cannot make assumptions on what its return value shall be.

Other answers have pointed out that by the standard you cannot rely on a move operation from a string object leaving that object empty.

However, you should expect that something more efficient than a copy is taking place. What is certainly happening is that your compiler's basic_string<>& operator=(basic_string<>&&) (the string 'move assignment') is implemented by swapping the two string objects (which is exactly what the standard sort of suggests: "Note: A valid implementation is swap(str).").

g++ apparently implements the string move assignment this way.

So you don't need to worry about efficiency - there should be no unnecessary copying of the string going on. However, you do need to make sure that the moved from string is cleared after the move, if you're going to use that object anymore.

Aside from what the others said about moving and using the moved object after that, a move is not exactly what you want to do here. What you conceptually want to is assign the content of _longest to longest_phrase and clear _longest . You were right in trying to avoid copying and reallocation, but you can achieve that easily by swapping:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM