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)
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;
}
...
- Self assignment test
- Strong exception guarantee
- 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;
}
...
- Self assignment test
- Strong exception guarantee
- 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;
}
...
- Self assignment test
- Strong exception guarantee
- 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;
}
...
- Self assignment test
- Strong exception guarantee
- 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;
}
...
- Self assignment test
- Strong exception guarantee
- 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 .
- 620