Int variable's value won't change after being moved

I've read the basics of move semantics and I did a couple of tests. Case #1:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
  #include <iostream>
#include <vector>
#include <string>
using namespace std;

int  main()
{
    string st = "hello";
    vector<string> vec;
    vec.push_back(st);
    cout << st;

    cin.get();
}

In this case, the program will not print anything because "hello" has been moved to vector[0].

Case #2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include <iostream>
#include <vector>

using namespace std;
int  main()
{
    int num=5;
    vector<int> vec;
    vec.push_back(num);
    cout << num;

    cin.get();
}



Why does the program print "5"? I thought num would be 0 or something undefined.
I've just run them in the shell with a few additions as well, these are my results.
Case #1:
Prints "hello".
If vec[0] is modified, it still prints "hello".

Case #2:
Prints 5.
If vec[0] is modified, it still prints 5.

These both show that push_back() makes a copy. The reference on this website is slightly ambiguous on this in that it says the passed variable is copied (or moved), I'm pretty sure this means copied unless explicitly moved (by using std::move()).
Last edited on
> The reference on this website is slightly ambiguous on this in that it says the passed variable is copied (or moved)

Not really. push_back() is overloaded: http://en.cppreference.com/w/cpp/container/vector/push_back
Normal overload resolution applies: lvalues are copied and rvalues are moved.

1
2
3
4
5
std::vector<std::string> vec;
vec.push_back( std::to_string(99) ) ; // rvalue, move
std::string str = std::to_string(99) ; // lvalue
vec.push_back( str ) ; // lvalue, copy
vec.push_back( "the value is: " + str ) ; // rvalue, move 


The reference on this site is accurate for C++11, and inaccurate - copied (or moved) - for C++98


> In this case, the program will not print anything because "hello" has been moved to vector[0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <vector>
#include <string>
#include <utility>

int  main()
{
    {
        // copied
        std::string st = "hello";
        std::vector<std::string> vec;
        vec.push_back(st); // copy, not move; st is still intact
        std::cout << "'" << st << "'\n" ; // prints "hello"

        int i = 78 ;
        int j = i ; // copy
        std::cout << i << ' ' << j << '\n' ; // prints 78 78
    }

    {
        // moved
        std::string st = "hello";
        std::vector<std::string> vec;
        
        vec.push_back( std::move(st) ) ; // moved; after this st is a valid, but unspecified state
        // std::string is a type defined by the standard library; for such types:
        // "Unless otherwise specified, such moved-from objects shall be
        // placed in a *valid* but *unspecified* state." - IS

        // all that the standard requires is that this would not engender undefined behaviour.
        std::cout << "'" << st << "'\n" ; //  typically, prints the empty string "" (does nothing)

        // note: for a user-defined type, the only requirement is that a moved-from object
        // is safely destructible. ie, its destructor will not engender undefined behaviour

        int i = 78 ;
        int j = std::move(i) ; // move; however int has a trivial move constructor
                               // ie. its move does the same thing as its trivial copy constructor
                               // ie. the int is copied/moved "as-if" by std::memmove()
                               // the original is value is still there after the move
        std::cout << i << ' ' << j << '\n' ; // prints 78 78
    }
}

http://coliru.stacked-crooked.com/a/73c268b75e43b3a2
As JLBorges showed it: You need to explicitely write std::move(...) in order to move a value. Otherwise it will be copied.

std::move(...) generates the move type && (only if there is a move constructor that takes &&)
Topic archived. No new replies allowed.