Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid use of move?

Could somebody give me hints on why this code doesn't output anything? I'm assuming it has something to do with the move line...

#include <iostream> 
#include <vector> 
#include <algorithm> 

using namespace std; 

int main(){ 
vector<int> v{66,79,154,24,76,13,7}; 

v = move(v); 
for(auto i: v) 
cout << i << " "; 
}

Update: So I added system("pause"); to help myself. Whether I need it or not is not what I'm focusing on. When I ran the code again in Visual Studio 2013, it worked. However, when I ran it through Ideone using C++14, it didn't output anything. Slightly confused now.

Visual Studio 2013 Ideone

like image 896
N. O'Neil Avatar asked Feb 12 '17 14:02

N. O'Neil


2 Answers

The standard library functions called with xvalue arguments may assume the argument is the only reference to the object; if it was constructed from an lvalue with std::move, no aliasing checks are made. In particular, this means that standard library move assignment operators do not have to perform self-assignment checks:

std::vector<int> v = {2, 3, 3};
v = std::move(v); // undefined behavior

For more detail please refer std::move and this question

like image 183
Shravan40 Avatar answered Oct 20 '22 22:10

Shravan40


I will have to say it's unreproducible.

I used my Visual studio 2015 Update 3 and the output is normal :

66 79 154 24 76 13 7

Moreover, under VC++ implementation there is no problem moving the vector to itself:

_Myt& operator=(_Myt&& _Right)
        {   // assign by moving _Right
        if (this != &_Right)
            {   // different, assign it
            clear();

        if (_Alty::propagate_on_container_move_assignment::value
            && this->get_allocator() != _Right.get_allocator())
            {   // assign vector, dumping proxy
            this->_Free_proxy();
            this->_Myvec = _STD move(_Right._Myvec);
            this->_Alloc_proxy();
            }
        else
            this->_Myvec = _STD move(_Right._Myvec);


        this->_Mysize = _Right._Mysize;
        _Right._Mysize = 0;
        }
    return (*this);
    }

as you can see from the condition this != &_Right, the moving will only happen if you are not moving a vector to itself.

EDIT:

apparently the compiler which is used to compile "C++14" on Ideone (GCC?) decides to not check self-move assignment and decides to free the vector data. as we can see from this little experiment, after the move the vector size is 0. as said in other previous answers/comments, assigning a move to itself is implementation defined. I guess VC++ does the right thing in this case.

EDIT 2:

it appears that GCC really doesn't check for self asignment. it moves the vector data into a temporary one, and takes __x data, which in that point is already empty. man, sometimes GCC behaves stupidly just for sake of false sense performance ( because cmp + jz are really going to slow your program down? please.)

like image 42
David Haim Avatar answered Oct 20 '22 21:10

David Haim