Move contructor/assignment

Hello there, can you please explain to me when a move constructor/assignment
is called and what exactly happens when so.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
string use(string& a)
{
    string tmp{ a };
    if (tmp.size()) tmp[0] = 'A';
    return tmp;
}

void f()
{
    string str = "Hello";
    string k = use(str);  // The move assignement is called here right?
    int a = 5;
    int b = static_cast<int&&>(a); // and here?
}
Last edited on
Line 11: Yes, the move constructor (not assignment) is called here, but I must point out that it's called after use() returns, not before. In other words, the string that's moved is the return value of use(), not str.
Line 13: I'm unclear what you're asking here. Yes, int::int(int &&) will be called, but the semantics of move constructors for PODs is identical to that of copy constructors. What I mean is that at line 14 a == 5; the value will be copied, not actually moved.

Also, generally one uses std::move() to explicitly request move construction and assignment, rather than static_cast.
The compiler will probably construct tmp directly in the place where k should be so that no copy or move is required at all.

https://www.fluentcpp.com/2016/11/28/return-value-optimizations/
EDIT: Missed Peter87's post earlier; leaving this post here because it has a snippet.

> The move assignement is called here right?

The copy constructor is invoked on line 3 in function use (to create the object tmp)

Copying of the local object with automatic storage duration is typically elided,
at least when optimisations are enabled (NRVO: named return value optimisation).

More information: https://en.cppreference.com/w/cpp/language/copy_elision

Snippet:
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
#include <iostream>

struct A
{
    A( int v ) : value(v) { std::cout << "constructor\n" ; }
    A( const A& that ) : value(that.value) { std::cout << "copy constructor\n" ; }
    A( A&& that ) /*noexcept*/ : value(that.value) { std::cout << "move constructor\n" ; }
    A& operator= ( const A& ) = default ;
    A& operator= ( A&& ) = default ;
    ~A() = default ;

    int value = 0 ;
};

A use( const A& a )
{
    A tmp { a } ; // copy constructor
    tmp.value = 777 ;
    std::cout << "returning local object tmp from function use\n" ;
    return tmp ;
}

int main()
{
    const A str = 8 ; // constructor

    const A k = use(str) ; // copy elision
    
    std::cout << "k.value == " << k.value << '\n' ; // 777
}

http://coliru.stacked-crooked.com/a/08d99d660d015452
http://rextester.com/FAN72683

Note: with the Microsoft compiler, disable optimisations (compile without the -Og option), and the local object with automatic storage duration is move constructed (NRVO is not applied).
http://rextester.com/DNMF78403

Last edited on
Topic archived. No new replies allowed.