how to check if c++ 11 move worked on rvalues

Hey,

Whats the best way to check if a rvalue really got moved and not copied? check/debug the move constructors?
Last edited on
If you use a debugger you could check if the move constructor or move assignment operator is called.
Another option: instrument the code

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <string>
#include <vector>

struct moveable
{
    moveable() = default ;
    moveable( std::string str ) : str(str) {}
    moveable( const moveable& ) = default ;
    moveable& operator= ( moveable& that ) = default ;
    ~moveable() = default ;

    moveable( moveable&& that ) noexcept : str( std::move(that.str) )
    { ++cnt_move_construct ; }

    moveable& operator= ( moveable&& that ) noexcept
    { str = std::move(that.str) ; ++cnt_move_assign ; return *this ; }

    std::string str ;

    static int cnt_move_construct ;
    static int cnt_move_assign ;
};

int moveable::cnt_move_construct = 0 ;
int moveable::cnt_move_assign = 0 ;

moveable foo() { return moveable{ "abcd" } ; }
moveable bar( moveable m ) { return m.str + m.str ; }

int main()
{
    moveable a ;
    std::cout << "move construct: " << moveable::cnt_move_construct // 0
              << "    move assign: " << moveable::cnt_move_assign << '\n' ; // 0

    moveable b = bar( foo() ) ; // copy-elision; no move or copy
    std::cout << "move construct: " << moveable::cnt_move_construct // 0
              << "    move assign: " << moveable::cnt_move_assign << '\n' ; // 0

    moveable c( std::move(a) ) ;
    std::cout << "move construct: " << moveable::cnt_move_construct // 1
              << "    move assign: " << moveable::cnt_move_assign << '\n' ; // 0

    b = std::move(c) ;
    std::cout << "move construct: " << moveable::cnt_move_construct // 1
              << "    move assign: " << moveable::cnt_move_assign << '\n' ; // 1

    std::vector<moveable> seq(100) ;
    seq.reserve(200) ;
    std::cout << "move construct: " << moveable::cnt_move_construct // 101
              << "    move assign: " << moveable::cnt_move_assign << '\n' ; // 1

    for( moveable& m : seq ) m = foo() ;
    std::cout << "move construct: " << moveable::cnt_move_construct // 101
              << "    move assign: " << moveable::cnt_move_assign << '\n' ; // 101
}

http://coliru.stacked-crooked.com/a/09158298dab67831
Tip: Remove the noexcept specification on move operations and rerun the code; try to explain the result

A third option: generate assembly code and look at it.

I tend to favour one of these; compiling with debug support will often skew the result because of the 'observer effect'.
The code that we observe will typically not be the code that runs when debug support is not enabled.
https://en.wikipedia.org/wiki/Observer_effect_(physics)
Topic archived. No new replies allowed.