OwnershiP And

Copy & move semantics

Copy & move semantics

                :::::-/:::/:`-:::. `/::-:::       
         ./::::o.   `.     `-`  `oo:-  .` .::o.   
     `:::o                       s:`        `s.   
    `s`                       `-:odh/::::://hs-`  
    -o                       :dmdhh.:y:  /y.ommdy-
   /:`                       `-:..o -o-  :o.`s/o+-
   y                             +-          s    
 -od:                            o`          s`   
/mmh`                            /:  `   `  `s    
:yo:/.                            +:`-:+:- .+.    
    `o.                            .:::s//:-`     
     -/-.                             `-o`        
      `.//   .                       //.`         
         ::o/:o.          `    -/+:-/-            
           s`-+/o/+:/:--:/s//os:.s``              
           s /-+-:/  ```` +.:///:+                
           hsysymdd       +hyh+mmm`               
           +yyo`::.       -yys`--.                
std::string data_1

copy

move

Copy & move semantics

                :::::-/:::/:`-:::. `/::-:::       
         ./::::o.   `.     `-`  `oo:-  .` .::o.   
     `:::o                       s:`        `s.   
    `s`                       `-:odh/::::://hs-`  
    -o                       :dmdhh.:y:  /y.ommdy-
   /:`                       `-:..o -o-  :o.`s/o+-
   y                             +-          s    
 -od:                            o`          s`   
/mmh`                            /:  `   `  `s    
:yo:/.                            +:`-:+:- .+.    
    `o.                            .:::s//:-`     
     -/-.                             `-o`        
      `.//   .                       //.`         
         ::o/:o.          `    -/+:-/-            
           s`-+/o/+:/:--:/s//os:.s``              
           s /-+-:/  ```` +.:///:+                
           hsysymdd       +hyh+mmm`               
           +yyo`::.       -yys`--.                
std::string data_1
If it were done, when ’tis done, then ’twere well
It were done quickly: if the assassination
Could trammel up the consequence, and catch
With his surcease success; that but this blow
Might be the be-all and the end-all – here,
But here, upon this bank and shoal of time,
We’d jump the life to come. But in these cases
We still have judgment here; that we but teach
Bloody instructions, which, being taught, return
To plague the inventor: this even-handed justice
Commends the ingredients of our poison’d chalice
To our own lips. He’s here in double trust:
First, as I am his kinsman and his subject,
Strong both against the deed; then, as his host,
Who should against his murderer shut the door,
Not bear the knife myself. Besides, this Duncan
Hath borne his faculties so meek, hath been
So clear in his great office, that his virtues
Will plead like angels, trumpet-tongu’d, against
The deep damnation of his taking-off;
And pity, like a naked new-born babe,
Striding the blast, or heaven’s Cherubins, hors’d
Upon the sightless couriers of the air,
Shall blow the horrid deed in every eye,
That tears shall drown the wind. I have no spur
To prick the sides of my intent, but only
Vaulting ambition, which o’erleaps itself
And falls on the other.
std::string data_2

copy

move

                :::::-/:::/:`-:::. `/::-:::       
         ./::::o.   `.     `-`  `oo:-  .` .::o.   
     `:::o                       s:`        `s.   
    `s`                       `-:odh/::::://hs-`  
    -o                       :dmdhh.:y:  /y.ommdy-
   /:`                       `-:..o -o-  :o.`s/o+-
   y                             +-          s    
 -od:                            o`          s`   
/mmh`                            /:  `   `  `s    
:yo:/.                            +:`-:+:- .+.    
    `o.                            .:::s//:-`     
     -/-.                             `-o`        
      `.//   .                       //.`         
         ::o/:o.          `    -/+:-/-            
           s`-+/o/+:/:--:/s//os:.s``              
           s /-+-:/  ```` +.:///:+                
           hsysymdd       +hyh+mmm`               
           +yyo`::.       -yys`--.                

copy

Copy & move semantics

                :::::-/:::/:`-:::. `/::-:::       
         ./::::o.   `.     `-`  `oo:-  .` .::o.   
     `:::o                       s:`        `s.   
    `s`                       `-:odh/::::://hs-`  
    -o                       :dmdhh.:y:  /y.ommdy-
   /:`                       `-:..o -o-  :o.`s/o+-
   y                             +-          s    
 -od:                            o`          s`   
/mmh`                            /:  `   `  `s    
:yo:/.                            +:`-:+:- .+.    
    `o.                            .:::s//:-`     
     -/-.                             `-o`        
      `.//   .                       //.`         
         ::o/:o.          `    -/+:-/-            
           s`-+/o/+:/:--:/s//os:.s``              
           s /-+-:/  ```` +.:///:+                
           hsysymdd       +hyh+mmm`               
           +yyo`::.       -yys`--.                
std::string data_1
If it were done, when ’tis done, then ’twere well
It were done quickly: if the assassination
Could trammel up the consequence, and catch
With his surcease success; that but this blow
Might be the be-all and the end-all – here,
But here, upon this bank and shoal of time,
We’d jump the life to come. But in these cases
We still have judgment here; that we but teach
Bloody instructions, which, being taught, return
To plague the inventor: this even-handed justice
Commends the ingredients of our poison’d chalice
To our own lips. He’s here in double trust:
First, as I am his kinsman and his subject,
Strong both against the deed; then, as his host,
Who should against his murderer shut the door,
Not bear the knife myself. Besides, this Duncan
Hath borne his faculties so meek, hath been
So clear in his great office, that his virtues
Will plead like angels, trumpet-tongu’d, against
The deep damnation of his taking-off;
And pity, like a naked new-born babe,
Striding the blast, or heaven’s Cherubins, hors’d
Upon the sightless couriers of the air,
Shall blow the horrid deed in every eye,
That tears shall drown the wind. I have no spur
To prick the sides of my intent, but only
Vaulting ambition, which o’erleaps itself
And falls on the other.
std::string data_2

copy

move

                :::::-/:::/:`-:::. `/::-:::       
         ./::::o.   `.     `-`  `oo:-  .` .::o.   
     `:::o                       s:`        `s.   
    `s`                       `-:odh/::::://hs-`  
    -o                       :dmdhh.:y:  /y.ommdy-
   /:`                       `-:..o -o-  :o.`s/o+-
   y                             +-          s    
 -od:                            o`          s`   
/mmh`                            /:  `   `  `s    
:yo:/.                            +:`-:+:- .+.    
    `o.                            .:::s//:-`     
     -/-.                             `-o`        
      `.//   .                       //.`         
         ::o/:o.          `    -/+:-/-            
           s`-+/o/+:/:--:/s//os:.s``              
           s /-+-:/  ```` +.:///:+                
           hsysymdd       +hyh+mmm`               
           +yyo`::.       -yys`--.                

copy

Copy & move semantics

                :::::-/:::/:`-:::. `/::-:::       
         ./::::o.   `.     `-`  `oo:-  .` .::o.   
     `:::o                       s:`        `s.   
    `s`                       `-:odh/::::://hs-`  
    -o                       :dmdhh.:y:  /y.ommdy-
   /:`                       `-:..o -o-  :o.`s/o+-
   y                             +-          s    
 -od:                            o`          s`   
/mmh`                            /:  `   `  `s    
:yo:/.                            +:`-:+:- .+.    
    `o.                            .:::s//:-`     
     -/-.                             `-o`        
      `.//   .                       //.`         
         ::o/:o.          `    -/+:-/-            
           s`-+/o/+:/:--:/s//os:.s``              
           s /-+-:/  ```` +.:///:+                
           hsysymdd       +hyh+mmm`               
           +yyo`::.       -yys`--.                
std::string data_1

copy

move

If it were done, when ’tis done, then ’twere well
It were done quickly: if the assassination
Could trammel up the consequence, and catch
With his surcease success; that but this blow
Might be the be-all and the end-all – here,
But here, upon this bank and shoal of time,
We’d jump the life to come. But in these cases
We still have judgment here; that we but teach
Bloody instructions, which, being taught, return
To plague the inventor: this even-handed justice
Commends the ingredients of our poison’d chalice
To our own lips. He’s here in double trust:
First, as I am his kinsman and his subject,
Strong both against the deed; then, as his host,
Who should against his murderer shut the door,
Not bear the knife myself. Besides, this Duncan
Hath borne his faculties so meek, hath been
So clear in his great office, that his virtues
Will plead like angels, trumpet-tongu’d, against
The deep damnation of his taking-off;
And pity, like a naked new-born babe,
Striding the blast, or heaven’s Cherubins, hors’d
Upon the sightless couriers of the air,
Shall blow the horrid deed in every eye,
That tears shall drown the wind. I have no spur
To prick the sides of my intent, but only
Vaulting ambition, which o’erleaps itself
And falls on the other.
std::string data_2

move

Copy & move semantics

std::string data_1

copy

move

If it were done, when ’tis done, then ’twere well
It were done quickly: if the assassination
Could trammel up the consequence, and catch
With his surcease success; that but this blow
Might be the be-all and the end-all – here,
But here, upon this bank and shoal of time,
We’d jump the life to come. But in these cases
We still have judgment here; that we but teach
Bloody instructions, which, being taught, return
To plague the inventor: this even-handed justice
Commends the ingredients of our poison’d chalice
To our own lips. He’s here in double trust:
First, as I am his kinsman and his subject,
Strong both against the deed; then, as his host,
Who should against his murderer shut the door,
Not bear the knife myself. Besides, this Duncan
Hath borne his faculties so meek, hath been
So clear in his great office, that his virtues
Will plead like angels, trumpet-tongu’d, against
The deep damnation of his taking-off;
And pity, like a naked new-born babe,
Striding the blast, or heaven’s Cherubins, hors’d
Upon the sightless couriers of the air,
Shall blow the horrid deed in every eye,
That tears shall drown the wind. I have no spur
To prick the sides of my intent, but only
Vaulting ambition, which o’erleaps itself
And falls on the other.
std::string data_2

move

                :::::-/:::/:`-:::. `/::-:::       
         ./::::o.   `.     `-`  `oo:-  .` .::o.   
     `:::o                       s:`        `s.   
    `s`                       `-:odh/::::://hs-`  
    -o                       :dmdhh.:y:  /y.ommdy-
   /:`                       `-:..o -o-  :o.`s/o+-
   y                             +-          s    
 -od:                            o`          s`   
/mmh`                            /:  `   `  `s    
:yo:/.                            +:`-:+:- .+.    
    `o.                            .:::s//:-`     
     -/-.                             `-o`        
      `.//   .                       //.`         
         ::o/:o.          `    -/+:-/-            
           s`-+/o/+:/:--:/s//os:.s``              
           s /-+-:/  ```` +.:///:+                
           hsysymdd       +hyh+mmm`               
           +yyo`::.       -yys`--.                

Copy & move semantics

std::string data_1

copy

move

std::string data_2

move

                :::::-/:::/:`-:::. `/::-:::       
         ./::::o.   `.     `-`  `oo:-  .` .::o.   
     `:::o                       s:`        `s.   
    `s`                       `-:odh/::::://hs-`  
    -o                       :dmdhh.:y:  /y.ommdy-
   /:`                       `-:..o -o-  :o.`s/o+-
   y                             +-          s    
 -od:                            o`          s`   
/mmh`                            /:  `   `  `s    
:yo:/.                            +:`-:+:- .+.    
    `o.                            .:::s//:-`     
     -/-.                             `-o`        
      `.//   .                       //.`         
         ::o/:o.          `    -/+:-/-            
           s`-+/o/+:/:--:/s//os:.s``              
           s /-+-:/  ```` +.:///:+                
           hsysymdd       +hyh+mmm`               
           +yyo`::.       -yys`--.                

Copy & move semantics

copy

move

std::string data_1
std::string data_2

move

                :::::-/:::/:`-:::. `/::-:::       
         ./::::o.   `.     `-`  `oo:-  .` .::o.   
     `:::o                       s:`        `s.   
    `s`                       `-:odh/::::://hs-`  
    -o                       :dmdhh.:y:  /y.ommdy-
   /:`                       `-:..o -o-  :o.`s/o+-
   y                             +-          s    
 -od:                            o`          s`   
/mmh`                            /:  `   `  `s    
:yo:/.                            +:`-:+:- .+.    
    `o.                            .:::s//:-`     
     -/-.                             `-o`        
      `.//   .                       //.`         
         ::o/:o.          `    -/+:-/-            
           s`-+/o/+:/:--:/s//os:.s``              
           s /-+-:/  ```` +.:///:+                
           hsysymdd       +hyh+mmm`               
           +yyo`::.       -yys`--.                

Copy & move semantics

copy

move

Swapping

data1
This is very long text. It takes linear time to copy it.
data2
Some more long text that cannot be quickly copied.
temporary
void swap(some_t& data1, some_t& data2) {
    some_t temporary = data1;
    data1 = data2;
    data2 = temporary;
}
This is very long text. It takes linear time to copy it.

Copy & move semantics

copy

move

Swapping

data1
This is very long text. It takes linear time to copy it.
data2
Some more long text that cannot be quickly copied.
temporary
void swap(some_t& data1, some_t& data2) {
    some_t temporary = data1;
    data1 = data2;
    data2 = temporary;
}
This is very long text. It takes linear time to copy it.
Some more long text that cannot be quickly copied.

Copy & move semantics

copy

move

Swapping

data1
data2
Some more long text that cannot be quickly copied.
temporary
void swap(some_t& data1, some_t& data2) {
    some_t temporary = data1;
    data1 = data2;
    data2 = temporary;
}
This is very long text. It takes linear time to copy it.
Some more long text that cannot be quickly copied.
This is very long text. It takes linear time to copy it.
This is very long text. It takes linear time to copy it.

Copy & move semantics

copy

move

Swapping

data1
data2
temporary
void swap(some_t& data1, some_t& data2) {
    some_t temporary = data1;
    data1 = data2;
    data2 = temporary;
}
This is very long text. It takes linear time to copy it.
Some more long text that cannot be quickly copied.
This is very long text. It takes linear time to copy it.
Some more long text that cannot be quickly copied.

Copy & move semantics

copy

move

Swapping

void swap(some_t& data1, some_t& data2) {
    some_t temporary = std::move(data1);
    data1 = std::move(data2);
    data2 = std::move(temporary);
}
void swap(some_t& data1, some_t& data2) {
    some_t temporary = data1;
    data1 = data2;
    data2 = temporary;
}

presumably > O(1)

presumably = O(1)

Copy & move semantics

copy

move

ClassName c1;

ClassName c2{c1};
ClassName c3 = c1;

Copy/Move

Construction

Copy/Move

Assignment

ClassName c1;

ClassName c2;
c2 = c1;

construction and assignment

value categories

Has identity No identity
lvalue rvalue

pre-C++11

type variable
object.member
assign = ment
++preincrement
ar[indexing]
...
42
comp < arison
&address
postincrement++
this
...
lvalue = ...
... = rvalue
rvalue = ...

but not

(if no const)

value categories

Has identity No identity
lvalue rvalue

Can move?

No???

Yes???

value categories

Has identity No identity
Cannot move lvalue
Can move rvalue

value categories

Has identity No identity
Cannot move lvalue ----------
Can move xvalue prvalue

xvalue - expiring value

prvalue - pure rvalue

value categories

xvalue - expiring value

prvalue - pure rvalue

glvalue - generalized lvalue

Has identity No identity
Cannot move lvalue ----------
Can move xvalue prvalue

glvalue

rvalue

copy semantics

copy

class Array {
private:
    int* data;
public:
    explicit Array(size_t capacity) :
        data{new int[capacity]}
    {
    }
    ~Array() {
        delete[] data;
    }
    //...
};
Array ar1{3};

copy semantics

copy

class Array {
private:
    int* data;
public:
    explicit Array(size_t capacity) :
        data{new int[capacity]}
    {
    }
    ~Array() {
        delete[] data;
    }
    //...
};
Array ar1{3};
Array ar2 = ar1;

copy semantics

copy

class Array {
private:
    int* data;
public:
    explicit Array(size_t capacity) :
        data{new int[capacity]}
    {
    }
    
    // implicitly-generated
    Array(const Array&) = default;
    Array(const Array& other) :
        data{other.data}
    {   // shallow copy
    }
    
    ~Array() {
        delete[] data;
    }
    //...
};
Array ar1{3};
Array ar2 = ar1;

copy semantics

copy

class Array {
private:
    int* data;
    int capacity;
public:
    explicit Array(size_t capacity) :
        data{new int[capacity]},
        capacity{capacity}
    {
    }
    Array(const Array& other) :
        data{new int[other.capacity]},
        capacity{other.capacity}
    {   // deep copy
        std::copy_n(other.data, capacity, data);
    }
    ~Array() {
        delete[] data;
    }
    //...
};
Array ar1{3};
Array ar2 = ar1;

copy Constructor

copy

class ClassName {
    T1 member1;
    T2 member2;
    T3 member3;
    // ...
    TN memberN;
    
    // copy constructor
    ClassName(const ClassName&);
    
    // defaulted copy constructor
    ClassName(const ClassName&) = default;
    ClassName(const ClassName& other) :
        member1{other.member1},
        member2{other.member2},
        member3{other.member3},
        // ...
        memberN{other.memberN}
    {
    }
    
    // deleted copy constructor
    ClassName(const ClassName&) = delete; 
};
ClassName(const ClassName&);
void f(ClassName byValue);
ClassName g();

ClassName h() {
    ClassName obj;

    // if no elision and not movable
    ClassName obj1 = g();
    ClassName obj2{obj};
    f(obj);
    return obj; // unless movable
}

copy Constructor

copy

class ClassName {
    T1 member1;
    T2 member2;
    T3 member3;
    // ...
    TN memberN;
    
    // copy constructor
    ClassName(const ClassName&);
    
    // defaulted copy constructor
    ClassName(const ClassName&) = default;
    ClassName(const ClassName& other) :
        member1{other.member1},
        member2{other.member2},
        member3{other.member3},
        // ...
        memberN{other.memberN}
    {
    }
    
    // deleted copy constructor
    ClassName(const ClassName&) = delete; 
};
ClassName(const ClassName&);
// if has move constructor
Classname obj1 = lvalue;
// otherwise
Classname obj2 = glvalue;
Has identity
Cannot move lvalue
Can move xvalue

glvalue

copy ELision

copy

ClassName func() {
    return prvalue;
}

func();

if returning prvalue

T f() {
    return T{};
}

T x = T{T{f()}};
T x = T{T{T{}}};
T x = T{T{}};
T x = T{};
T x{};

if initializer is a prvalue and of same type

(and move)

Has identity No identity
Cannot move lvalue ----------
Can move xvalue prvalue

glvalue

rvalue

copy ELision

copy

(and move)

\Downarrow

no side effects

in copy and move constructors

copy Assignment

copy

class Array {
private:
    int* data;
    int capacity;
public:
    explicit Array(size_t capacity) :
        data{new int[capacity]},
        capacity{capacity}
    {
    }
    Array(const Array& other) :
        data{new int[other.capacity]},
        capacity{other.capacity}
    {   // deep copy
        std::copy_n(other.data, capacity, data);
    }
    Array& operator=(const Array& other) {
        if (this != &other) {
            int* newData = new int[other.capacity];
            std::copy_n(other.data, other.capacity, newData);

            delete[] data;
            capacity = other.capacity;
            data = newData;
        }
        return *this;
    }
    ~Array() {
        delete[] data;
    }
    //...
};
Array ar1{3};
Array ar2{5};

ar2 = ar1;

copy assignment

copy

class ClassName {
    T1 member1;
    T2 member2;
    T3 member3;
    // ...
    TN memberN;
    
    // copy assignment operator
    ClassName& operator=(const ClassName&);
    
    // defaulted copy assignment operator
    ClassName& operator=(const ClassName&) = default;
    ClassName& operator=(const ClassName& other)
    {
        member1 = other.member1;
        member2 = other.member2;
        member3 = other.member3;
        // ...
        memberN = other.memberN;
    }
    
    // deleted copy assignment operator
    ClassName(const ClassName&) = delete; 
};
ClassName& operator=(const ClassName&);
ClassName obj;

// if has mv asgn op
obj = lvalue;
// otherwise
obj = glvalue;
ClassName& operator=(ClassName); // copy and swap idiom
Has identity
Cannot move lvalue
Can move xvalue

glvalue

ownership

char* concat(const char* str1, const char* str2) {
    size_t len1 = strlen(str1);
    size_t len2 = strlen(str2);
    size_t len = len1 + len2 + 1;
    
    char* result = new char[len];
    strcpy(result, str1);
    strcpy(result + len1, str2);
    result[len - 1] = '\0';
    
    return result;
}
void user() {
    const char* str = concat("Hello ", "World!");
    printMessage(str);
} // leak
size_t GetClipboardSize();
void GetClipboard(char* const);

char* const getClipboard() {   
    size_t len = GetClipboardSize();
    static char* const contents{};
    delete[] contents;
    contents = new char[len];
    GetClipboard(contents);
    
    return contents;
}
void user() {
    auto contents = GetClipboard();
    printMessage(contents);
    delete[] contents; // double del
}

ownership

char* concat(const char* str1, const char* str2) {
    size_t len1 = strlen(str1);
    size_t len2 = strlen(str2);
    size_t len = len1 + len2 + 1;
    
    char* result = new char[len];
    strcpy(result, str1);
    strcpy(result + len1, str2);
    result[len - 1] = '\0';
    
    return result;
}
void user() {
    const char* str = concat("Hello ", "World!");
    printMessage(str);
    delete[] str;
}
size_t GetClipboardSize();
void GetClipboard(char* const);

char* const getClipboard() {   
    size_t len = GetClipboardSize();
    static char* const contents{};
    delete[] contents;
    contents = new char[len];
    GetClipboard(contents);
    
    return contents;
}
void user() {
    printMessage(GetClipboard());
}

ownership

#include <string>
void user() {
    printMessage(std::string{"Hello "} + "World!");
    // printMessage("Hello " "World!");
    // using namespace std::string_literals;
    // printMessage("Hello "s + "World!");
}
void user() {
    printMessage(GetClipboard());
}
char* concat(const char* str1, const char* str2) {
    size_t len1 = strlen(str1);
    size_t len2 = strlen(str2);
    size_t len = len1 + len2 + 1;
    
    char* result = new char[len];
    strcpy(result, str1);
    strcpy(result + len1, str2);
    result[len - 1] = '\0';
    
    return result;
}
size_t GetClipboardSize();
void GetClipboard(char* const);

std::string getClipboard() {   
    size_t len = GetClipboardSize();
    std::string contents;
    contents.resize(len);
    GetClipboard(contents.data());
    
    return contents;
}

ownership

data1
Some more long text that cannot be quickly copied.


resposibility

to clean up

data2

ownership

data1
Some more long text that cannot be quickly copied.


resposibility

to clean up

data2

move

move semantics

move

class Array {
private:
    int* data;
    int capacity;
public:
    explicit Array(size_t capacity) :
        data{new int[capacity]},
        capacity{capacity}
    {
    }
    Array(Array&& other) noexcept :
        data{other.data},
        capacity{other.capacity}
    {
        other.data = nullptr;
        other.capacity = 0;
    }
    ~Array() {
        delete[] data;
    }
    //...
};
Array ar1{3};
Array ar2 = std::move(ar1);

move semantics

move

class Array {
private:
    int* data;
    int capacity;
public:
    explicit Array(size_t capacity) :
        data{new int[capacity]},
        capacity{capacity}
    {
    }
    Array(Array&& other) noexcept :
        data{std::exchange(other.data, nullptr)},
        capacity{std::exchange(other.capacity, 0)}
    {
    }
    ~Array() {
        delete[] data;
    }
    //...
};
Array ar1{3};
Array ar2 = std::move(ar1);

move semantics

move

class Array {
private:
    int* data;
    int capacity;
public:
    explicit Array(size_t capacity) :
        data{new int[capacity]},
        capacity{capacity}
    {
    }
    Array(Array&& other) noexcept :
        data{std::exchange(other.data, nullptr)},
        capacity{std::exchange(other.capacity, 0)}
    {
    }
    ~Array() {
        delete[] data;
    }
    //...
};
Array ar1{3};
Array ar2 = std::move(ar1);
template <typename T>
std::remove_reference_t<T>&& move(T&& arg) {
    return static_cast<remove_reference_t<T>&&>(arg);
}

move constructor

move

class ClassName {
    T1 member1;
    T2 member2;
    T3 member3;
    // ...
    TN memberN;
    
    // move constructor
    ClassName(ClassName&&);
    
    // defaulted move constructor
    ClassName(ClassName&&) = default;
    ClassName(ClassName&& other) :
        member1{std::move(other.member1)},
        member2{std::move(other.member2)},
        member3{std::move(other.member3)},
        // ...
        memberN{std::move(other.memberN)}
    {
    }
    
    // deleted move constructor
    ClassName(ClassName&&) = delete; 
};
ClassName(ClassName&&);
void f(ClassName byValue);
ClassName g();

ClassName g() {
    ClassName obj;

    ClassName obj1 = g(); // if no elision
    ClassName obj2{std::move(obj)};
    f(std::move(obj));
    return obj;
}

move constructor

move

class ClassName {
    T1 member1;
    T2 member2;
    T3 member3;
    // ...
    TN memberN;
    
    // move constructor
    ClassName(ClassName&&);
    
    // defaulted move constructor
    ClassName(ClassName&&) = default;
    ClassName(ClassName&& other) :
        member1{std::move(other.member1)},
        member2{std::move(other.member2)},
        member3{std::move(other.member3)},
        // ...
        memberN{std::move(other.memberN)}
    {
    }
    
    // deleted move constructor
    ClassName(ClassName&&) = delete; 
};
ClassName(ClassName&&);
Classname obj = xvalue
// move elision if prvalue
Has identity
Cannot move lvalue
Can move xvalue

glvalue

Move Assignment

Move

class Array {
private:
    int* data;
    int capacity;
public:
    explicit Array(size_t capacity) :
        data{new int[capacity]},
        capacity{capacity}
    {
    }
    Array(Array&& other) noexcept :
        data{std::exchange(other.data, nullptr)},
        capacity{std::exchange(other.capacity, 0)}
    {
    }
    Array& operator=(Array&& other) noexcept
    {
        data = std::exchange(other.data, nullptr);
        capacity = std::exchange(other.capacity, 0);
    }
    ~Array() {
        delete[] data;
    }
    //...
};
Array ar1{3};
Array ar2{5};

ar2 = std::move(ar1);

Move assignment

move

class ClassName {
    T1 member1;
    T2 member2;
    T3 member3;
    // ...
    TN memberN;
    
    // move assignment operator
    ClassName& operator=(const ClassName&);
    
    // defaulted move assignment operator
    ClassName& operator=(ClassName&&) = default;
    ClassName& operator=(ClassName&& other)
    {
        member1 = std::move(other.member1);
        member2 = std::move(other.member2);
        member3 = std::move(other.member3);
        // ...
        memberN = std::move(other.memberN);
    }
    
    // deleted move assignment operator
    ClassName(ClassName&&) = delete; 
};
ClassName& operator=(ClassName&&);
ClassName& operator=(ClassName); // copy and swap idiom
Classname obj = xvalue
// move elision if prvalue
Has identity
Cannot move lvalue
Can move xvalue

glvalue

Copy & move semantics

copy

move

obj = value;

xvalue

prvalue

lvalue

Has identity No identity
Cannot move lvalue ----------
Can move xvalue prvalue

glvalue

rvalue

copy

constructor/

assignment operator

copy

constructor/

assignment operator

move

/

elision/

assignment operator

move

Exception safety

Basic exception guarantee - valid, unspecified state; invariants maintained

No exception guarantee - undefined state

Array& operator=(const Array& other)
{
    if (this == &other) return *this;
    delete[] data;
    data = new int[other.capacity];
    capacity = other.capacity;
    std::copy_n(other.data, capacity, data);
    return *this;
}
Array& operator=(const Array& other)
{
    if (this == &other) return *this;
    delete[] data;
    capacity = 0;
    data = new int[other.capacity];
    capacity = other.capacity;
    std::copy_n(other.data, capacity, data);
    return *this;
}

Exception safety

Nothrow exception guarantee - cannot fail

Strong exception guarantee - previous state restored

Array& operator=(const Array& other) {
    if (this != &other) {
        int* newData = new int[other.capacity];
        std::copy_n(other.data, other.capacity, newData);

        delete[] data;
        capacity = other.capacity;
        data = newData;
    }
    return *this;
}
Array& operator=(Array&& other) noexcept {
    data = std::exchange(other.data, nullptr);
    capacity = std::exchange(other.capacity, 0);
}

copy and swap idiom

ClassName& operator=(ClassName);

copy

swap

...

Array(const Array& other) :
    data{new int[other.capacity]},
    capacity{other.capacity}
{   
    std::copy_n(other.data, capacity, data);
}
Array& operator=(const Array& other) {
    capacity = other.capacity;
        
    delete[] data;
    data = new int[capacity];
    std::copy_n(other.data, capacity, data);
        
    return *this;
}

...
  1. Self assignment test
  2. Strong exception guarantee
  3. Code duplication

Problems:

copy and swap idiom

ClassName& operator=(ClassName);

copy

swap

...

Array(const Array& other) :
    data{new int[other.capacity]},
    capacity{other.capacity}
{   
    std::copy_n(other.data, capacity, data);
}
Array& operator=(const Array& other) {
    if (this != &other) {
        capacity = other.capacity;
        
        delete[] data;
        data = new int[capacity];
        std::copy_n(other.data, capacity, data);
    }
    return *this;
}

...
  1. Self assignment test
  2. Strong exception guarantee
  3. Code duplication

Problems:

copy and swap idiom

ClassName& operator=(ClassName);

copy

swap

...

Array(const Array& other) :
    data{new int[other.capacity]},
    capacity{other.capacity}
{   
    std::copy_n(other.data, capacity, data);
}
Array& operator=(const Array& other) {
    if (this != &other) {
        capacity = other.capacity;
        
        delete[] data;
        data = new int[capacity];
        std::copy_n(other.data, capacity, data);
    }
    return *this;
}

...
  1. Self assignment test
  2. Strong exception guarantee
  3. Code duplication

Problems:

copy and swap idiom

ClassName& operator=(ClassName);

copy

swap

...

Array(const Array& other) :
    data{new int[other.capacity]},
    capacity{other.capacity}
{   
    std::copy_n(other.data, capacity, data);
}
Array& operator=(const Array& other) {
    if (this != &other) {
        int* newData = new int[other.capacity];
        std::copy_n(other.data, other.capacity, newData);
        delete[] data;
        capacity = other.capacity;
        data = newData;
    }
    return *this;
}

...
  1. Self assignment test
  2. Strong exception guarantee
  3. Code duplication

Problems:

copy and swap idiom

ClassName& operator=(ClassName);

copy

swap

...

Array(const Array& other) :
    data{new int[other.capacity]},
    capacity{other.capacity}
{   
    std::copy_n(other.data, capacity, data);
}
Array& operator=(const Array& other) {
    if (this != &other) {
        int* newData = new int[other.capacity];
        std::copy_n(other.data, other.capacity, newData);
        delete[] data;
        capacity = other.capacity;
        data = newData;
    }
    return *this;
}

...
  1. Self assignment test
  2. Strong exception guarantee
  3. Code duplication

Problems:

copy and swap idiom

ClassName& operator=(ClassName);

copy

swap

Array(const Array& other) :
    data{new int[other.capacity]},
    capacity{other.capacity}
{   
    std::copy_n(other.data, capacity, data);
}
Array(Array&& other) noexcept :
    data{std::exchange(other.data, nullptr)},
    capacity{std::exchange(other.capacity, 0)}
{
}
Array& operator=(const Array& other) {
    if (this != &other) {
        int* newData = new int[other.capacity];
        std::copy_n(other.data, other.capacity, newData);
        delete[] data;
        capacity = other.capacity;
        data = newData;
    }
    return *this;
}
Array& operator=(Array&& other) noexcept {
    data = std::exchange(other.data, nullptr);
    capacity = std::exchange(other.capacity, 0);
}

copy and swap idiom

ClassName& operator=(ClassName);

copy

swap

Array() :
    data{nullptr},
    capacity{0}
{
}
Array(const Array& other) :
    data{new int[other.capacity]},
    capacity{other.capacity}
{   
    std::copy_n(other.data, capacity, data);
}
Array(Array&& other) noexcept : Array{} {
    swap(*this, other);
}
Array& operator=(Array other) {
    swap(*this, other);
    return *this;
}
friend void swap(Array& lhs, Array& rhs) noexcept {
    using std::swap; // ADL

    swap(lhs.capacity, rhs.capacity);
    swap(lhs.data, rhs.data);
}

rule of 5 & Rule of 0

5

0

If a class has a user-defined or deleted [any of the below]:
 

 

 

 

 

It should have them all user-defined.

Rule of 5

Rule of 0

If a class doesn't deal with ownership, it shouldn't have a user-defined or deleted [any of the above].
  • copy constructor
  • copy assignment operator
  • move constructor
  • move assignment operator
  • destructor

type traits

#include <type_traits>

std::is_copy_constructible_v<T>
std::is_trivially_copy_constructible_v<T>
std::is_nothrow_copy_constructible_v<T>

std::is_move_constructible_v<T>
std::is_trivially_move_constructible_v<T>
std::is_nothrow_move_constructible_v<T>

std::is_assignable_v<T>
std::is_trivially_assignable_v<T>
std::is_nothrow_assignable_v<T>

std::is_copy_assignable_v<T>
std::is_trivially_copy_assignable_v<T>
std::is_nothrow_copy_assignable_v<T>

std::is_move_assignable_v<T>
std::is_trivially_move_assignable_v<T>
std::is_nothrow_move_assignable_v<T>

OwnershiP And

Copy & move semantics

RAII

inheritance

virtual

  • constructor
  • member initializer list
  • destructor
  • default constructor
  • std::initializer_list
  • in-class initializer
  • copy ctor
  • cpy assign op
  • move ctor
  • mv assign op
  • default members
  • deleted members
  • rule of 0
  • rule of 3/5
  • smart-ptrs
  • converting constructor
  • explicit specifier
  • is-a relation
  • has-a relation
  • public inheritance
  • final specifier
  • using declaration
  • empty base optimization
  • protected members
  • private & protected inheritance
  • multiple inheritance
  • diamond problem
  • base method hiding problem
  • virtual methods
  • override specifier
  • dynamic type
    • RTTI
    • dynamic_cast
    • typeid
    • vtables
  • by value passing problem
  • pure virtual function
  • abstract class

misc

  • friends
  • nested members
  • conversion operators
  • operator overloading
  • member pointers
  • unions
    • std optional
    • std variant
    • std any

Ownership and Copy & Move Semantics

By Jan Bielak

Ownership and Copy & Move Semantics

A presentation about ownership, copy semantics and move semantics covering copy constructors, move constructors, copy assignment operators, move assignment operators, the rule of 0, the rule of 5, as well as value categories, exception guarantees and the copy-swap idiom. It is presented here: https://www.youtube.com/watch?v=zN45skruTvI .

  • 234