TDDE18 & 726G77 Classes & Pointers Christoffer Holm - - PowerPoint PPT Presentation

tdde18 726g77
SMART_READER_LITE
LIVE PREVIEW

TDDE18 & 726G77 Classes & Pointers Christoffer Holm - - PowerPoint PPT Presentation

TDDE18 & 726G77 Classes & Pointers Christoffer Holm Department of Computer and informaon science 1 Classes 2 Pointers 3 List lab 4 Special Member Funcons 2 / 82 Classes What is a class? struct Date { int day; int month;


slide-1
SLIDE 1

TDDE18 & 726G77

Classes & Pointers

Christoffer Holm

Department of Computer and informaon science

slide-2
SLIDE 2

1 Classes 2 Pointers 3 List lab 4 Special Member Funcons

slide-3
SLIDE 3

2 / 82

Classes

What is a class?

struct Date { int day; int month; int year; }; bool operator<(Date d1, Date d2) { // ... } Date next_date(Date d) { // ... }

slide-4
SLIDE 4

2 / 82

Classes

What is a class?

struct Date { int day; int month; int year; }; bool operator<(Date d1, Date d2) { // ... } Date next_date(Date d) { // ... } class Date { public: int day; int month; int year; bool operator<(Date d) { // ... } Date next_date() { // ... } };

slide-5
SLIDE 5

3 / 82

Classes

What is a class?

‚ A class is like a struct. ‚ With classes we couple data and funconality. ‚ That is; we store the funcons and the data in a neatly packaged structure called a class.

slide-6
SLIDE 6

4 / 82

Classes

How does it work?

Date today {27, 9, 2019}; Date tomorrow {next_date(today)}; if (today < tomorrow) { // ... }

slide-7
SLIDE 7

4 / 82

Classes

How does it work?

Date today {27, 9, 2019}; Date tomorrow {next_date(today)}; if (today < tomorrow) { // ... } Date today {27, 9, 2019}; Date tomorrow {today.next_date()}; if (today < tomorrow) { // ... }

slide-8
SLIDE 8

4 / 82

Classes

How does it work?

Date today {27, 9, 2019}; Date tomorrow {next_date(today)}; if (operator<(today, tomorrow)) { // ... } Date today {27, 9, 2019}; Date tomorrow {today.next_date()}; if (today.operator<(tomorrow)) { // ... }

slide-9
SLIDE 9

5 / 82

Classes

How does it work?

‚ The funcons that are declared inside a class are called member funcons. ‚ They are not like ordinary funcons, because they have a hidden argument. ‚ The hidden argument is the object we are calling this funcon from. ‚ A member funcon is called like this: obj.function() where obj is the current object we are calling this funcon on (the hidden parameter).

slide-10
SLIDE 10

6 / 82

Classes

this

struct Date { // ... }; void increase_year(Date& date) { ++(date.year); } // ... class Date { // ... void increase_year() { ++(this->year); } // ... };

slide-11
SLIDE 11

6 / 82

Classes

this

struct Date { // ... }; void increase_year(Date& date) { ++(date.year); } // ... class Date { // ... void increase_year() { ++year; } // ... };

slide-12
SLIDE 12

7 / 82

Classes

this

‚ You can access this hidden parameter through the this keyword. ‚ Instead of accessing data members (fields) through . we use -> for this. ‚ However, most of the me we don’t need to use this at all. ‚ As long as there is no ambiguity what is meant we can just skip this-> completely.

slide-13
SLIDE 13

8 / 82

Classes

When is this mandatory? class Date { // ... void set_year(int year) { year = year; } };

slide-14
SLIDE 14

8 / 82

Classes

When is this mandatory? class Date { // ... void set_year(int year) { this->year = year; } };

slide-15
SLIDE 15

8 / 82

Classes

When is this mandatory? class Date { // ... void set_year(int y) { year = y; } };

slide-16
SLIDE 16

9 / 82

Classes

When is this mandatory?

‚ When there is a more local variable with the same name as the member you are trying to access. ‚ In this example we have two things called year, the data member in the class and the parameter. ‚ The parameter is closer (more local), so the compiler will automacally choose that whenever we just write

year.

‚ In this case we have to further specify that it is the member we want, which we do by using this.

slide-17
SLIDE 17

10 / 82

Classes

Why though? Date today {27, 9, 2019}; today.day = 48; // should not be allowed

slide-18
SLIDE 18

11 / 82

Classes

Why though?

‚ When coupling data and funconality we want the user

  • f our class to only use the specified funcons.

‚ The user should not have the power to modify data fields however they want. ‚ In this case this would allow the user to set a nonsensical value to data members. ‚ Therefore it would be nice to hide things inside our class. ‚ This is done with access levels.

slide-19
SLIDE 19

12 / 82

Classes

private & public

class Date { public: bool operator<(Date const& d) const { // ... } Date next_date() { // ... } private: int day; int month; int year; };

slide-20
SLIDE 20

12 / 82

Classes

private & public

class Date { public: bool operator<(Date const& d) const { // ... } Date next_date() { // ... } private: int day; int month; int year; }; int main() { Date today {27, 9, 2019}; // not allowed today.day = 48; }

slide-21
SLIDE 21

12 / 82

Classes

private & public

class Date { public: bool operator<(Date const& d) const { // ... } Date next_date() { // ... } private: int day; int month; int year; }; int main() { // will not work Date today {27, 9, 2019}; // not allowed today.day = 48; }

slide-22
SLIDE 22

13 / 82

Classes

private & public

‚ We can start blocks of access levels. ‚ All funcons and data members placed aer a public declaraon will be freely available from outside of the class through an object. ‚ All members placed aer a private declaraon will

  • nly be accessible from inside the member funcons.

‚ I.e. private allows us to hide away things that only the class is allowed to see.

slide-23
SLIDE 23

14 / 82

Classes

private & public

‚ However there is a problem. ‚ Once the data members are private the compiler cannot inialize those data members as they are now

private, meaning only a member funcon has access

to them. ‚ Fortunately we can create special member funcons called constructors that handles the inializaon of data members.

slide-24
SLIDE 24

15 / 82

Classes

Constructors

class Date { public: Date(int d, int m, int y) // member initialization list : day{d}, month{m}, year{y} { } // ... private: int day; int month; int year; };

slide-25
SLIDE 25

15 / 82

Classes

Constructors

class Date { public: Date(int d, int m, int y) // member initialization list : day{d}, month{m}, year{y} { } // ... private: int day; int month; int year; }; int main() { // works! Date today {27, 9, 2019}; // not allowed today.day = 48; }

slide-26
SLIDE 26

16 / 82

Classes

Constructors

‚ Constructors work like normal funcons with 2 excepons: ‚ A constructor is only called when an object is created, ‚ they inializes variables inside the member inializaon list.

slide-27
SLIDE 27

17 / 82

Classes

Constructors

‚ You can declare mulple constructors as long as they have a unique set of parameters. ‚ When inializing the object the user passes in parameters and the appropriate constructor will be called based on the parameters passed in.

slide-28
SLIDE 28

18 / 82

Classes

Member inializaon list

‚ The member inializaon list is a comma-separated list

  • f all the data members that this constructor is

supposed to inialize. ‚ Each member in the list must be inialized with either

{...} or (...).

slide-29
SLIDE 29

19 / 82

Classes

Declaraon & Definion

class Date; // class declaration class Date // class definition { // ... Date(int d, int m, int y); // declare a construtor void increase_year(); // declare a member function // ... private: // data members int day; int month; int year; }; Date::Date(int d, int m, int y) // define a construtor : day{d}, month{m}, year{y} // member initialization list { } void Date::increase_year() // define a member function { ++year; }

slide-30
SLIDE 30

20 / 82

Classes

Declaraon & Definion

‚ It is possible to declare a class before defining it, just as we can do with funcons. ‚ You can also declare member funcons before defining them. ‚ To define a member funcon aer the class has been defined you add the ClassName:: before the member funcon name to communicate which class this member funcon resides in.

slide-31
SLIDE 31

21 / 82

Classes

const member funcons class Date { // ... int get_day() { day = 7; // allowed return day; } };

slide-32
SLIDE 32

21 / 82

Classes

const member funcons class Date { // ... int get_day() const { day = 7; // NOT allowed return day; } };

slide-33
SLIDE 33

22 / 82

Classes

const member funcons

‚ Inside a member funcon you have access to private data members. ‚ This means that a funcon can modify these members however they want. ‚ If another programmer decides to use your funcon they might not expect it to modify anything. ‚ You can declare your member funcons as const which disallows they modificaon of data members inside this specific funcon.

slide-34
SLIDE 34

23 / 82

Classes

const member funcons

You might want to do this for two major reasons:

  • 1. This makes sure that you, the programmer doesn’t

accidentally change a variable when you are not supposed to.

  • 2. It also communicates to other programmers that this

member funcon won’t change the state of the object, meaning it is always safe to call in all contexts.

slide-35
SLIDE 35

24 / 82

Classes

const member funcons

class Date { // ... int get_day() { return day; } // ... }; Date d1{27, 9, 2019}; cout << d1.get_day() << endl; Date const d2{28, 9, 2019}; // doesn't work cout << d2.get_day() << endl;

slide-36
SLIDE 36

24 / 82

Classes

const member funcons

class Date { // ... int get_day() const { return day; } // ... }; Date d1{27, 9, 2019}; cout << d1.get_day() << endl; Date const d2{28, 9, 2019}; // works! cout << d2.get_day() << endl;

slide-37
SLIDE 37

25 / 82

Classes

const member funcons

‚ If an object is declared as const then no data members can be modified. ‚ This means that only member funcons that are declared as const are allowed to be called from these

  • bjects, with the excepon of constructors and the

destructor.

slide-38
SLIDE 38

26 / 82

Classes

Inner class

class Outer { public: void fun(); class Inner { public: void fun(); }; }; void Outer::fun() { // ... } void Outer::Inner::fun() { // ... } Outer o{};

  • .fun();

Outer::Inner i{}; // works! i.fun();

slide-39
SLIDE 39

26 / 82

Classes

Inner class

class Outer { public: void fun(); private: class Inner { public: void fun(); }; }; void Outer::fun() { // ... } void Outer::Inner::fun() { // ... } Outer o{};

  • .fun();

Outer::Inner i{}; // doesn't work i.fun();

slide-40
SLIDE 40

27 / 82

Classes

Inner class

‚ It is possible to declare classes inside other classes. ‚ These classes adhere to the access level they are placed in. ‚ Meaning an inner class declared as private is not accessible from the outside. ‚ To define member funcons of an inner class you first have to access the outer class, and then the inner class. ‚ So you write Outer::Inner:: before the funcon name.

slide-41
SLIDE 41

28 / 82

Classes

friend

class Date { // ... private: int day; int month; int year; friend bool same_month(Date d1, Date d2); }; bool same_month(Date d1, Date d2) { return d1.year == d2.year && d1.month == d2.month; }

slide-42
SLIDE 42

29 / 82

Classes

friend

‚ It is possible to declare a funcon as a friend to your class. ‚ This allows that friend to access the private members. ‚ Should only be used if absolutely necessary, since it couples the class with a funcon that is not a member.

slide-43
SLIDE 43

1 Classes 2 Pointers 3 List lab 4 Special Member Funcons

slide-44
SLIDE 44

31 / 82

Pointers

What is a pointer? int x{5}; int y{7};

slide-45
SLIDE 45

31 / 82

Pointers

What is a pointer? int x{5}; int y{7};

x

5

y

7

slide-46
SLIDE 46

31 / 82

Pointers

What is a pointer? int x{5}; int y{7}; int* ptr{};

x

5

y

7

slide-47
SLIDE 47

31 / 82

Pointers

What is a pointer? int x{5}; int y{7}; int* ptr{};

x

5

y

7

ptr

slide-48
SLIDE 48

31 / 82

Pointers

What is a pointer? int x{5}; int y{7}; int* ptr{&x};

x

5

y

7

ptr

slide-49
SLIDE 49

31 / 82

Pointers

What is a pointer? int x{5}; int y{7}; int* ptr{&x};

x

5

y

7

ptr

slide-50
SLIDE 50

31 / 82

Pointers

What is a pointer? int x{5}; int y{7}; int* ptr{&x}; ptr = &y;

x

5

y

7

ptr

slide-51
SLIDE 51

31 / 82

Pointers

What is a pointer? int x{5}; int y{7}; int* ptr{&x}; ptr = &y;

x

5

y

7

ptr

slide-52
SLIDE 52

32 / 82

Pointers

What is a pointer?

‚ A pointer is a variable that stores an address to some locaon in memory. ‚ A pointer can only point to a specific data type (specified by the programmer). ‚ This means that when the pointer retrieves the value stored at the address, it will always be the specified type. ‚ Read pointer declaraons backwards: int* x reads: x is a pointer(*) to an int.

slide-53
SLIDE 53

33 / 82

Pointers

What is a pointer?

‚ Each variable has a locaon in memory (they have an address) which can be retrieved with operator&, as such: &x. ‚ A pointer can therefore work like a reference, by storing a specific variables address in the pointer. ‚ The difference between a reference and a pointer is that pointers can change what they point to while references cannot.

slide-54
SLIDE 54

34 / 82

Pointers

How to use a pointer int x{5}; int *ptr{&x}; cout << *ptr << endl;

x

5

ptr

slide-55
SLIDE 55

34 / 82

Pointers

How to use a pointer int x{5}; int *ptr{&x}; cout << *ptr << endl;

x

5

ptr

slide-56
SLIDE 56

34 / 82

Pointers

How to use a pointer int x{5}; int *ptr{&x}; cout << *ptr << endl;

x

5

ptr

slide-57
SLIDE 57

35 / 82

Pointers

How to use a pointer

‚ To access the data on the other end of the pointer (i.e. the thing it points to) we have to dereference the pointer. ‚ You dereference a pointer with operator*. ‚ Like this: *ptr.

slide-58
SLIDE 58

36 / 82

Pointers

Poinng to nothing int* ptr{}; ptr == nullptr;

slide-59
SLIDE 59

37 / 82

Pointers

Poinng to nothing

‚ The default value of pointers is a special value called

nullptr.

‚ A pointer that is nullptr points at nothing. ‚ This is also a big difference between pointers and references; a reference must refer to something.

slide-60
SLIDE 60

38 / 82

Pointers

Manual memory int* ptr{};

slide-61
SLIDE 61

38 / 82

Pointers

Manual memory int* ptr{};

ptr

slide-62
SLIDE 62

38 / 82

Pointers

Manual memory int* ptr{new int{5}};

ptr

slide-63
SLIDE 63

38 / 82

Pointers

Manual memory int* ptr{new int{5}};

ptr

5

slide-64
SLIDE 64

38 / 82

Pointers

Manual memory int* ptr{new int{5}};

ptr

5

slide-65
SLIDE 65

38 / 82

Pointers

Manual memory int* ptr{new int{5}}; *ptr = 7;

ptr

5

slide-66
SLIDE 66

38 / 82

Pointers

Manual memory int* ptr{new int{5}}; *ptr = 7;

ptr

7

slide-67
SLIDE 67

38 / 82

Pointers

Manual memory int* ptr{new int{5}}; *ptr = 7; delete ptr;

ptr

7

slide-68
SLIDE 68

38 / 82

Pointers

Manual memory int* ptr{new int{5}}; *ptr = 7; delete ptr;

ptr

slide-69
SLIDE 69

38 / 82

Pointers

Manual memory int* ptr{new int{5}}; *ptr = 7; delete ptr; ptr = nullptr;

ptr

slide-70
SLIDE 70

38 / 82

Pointers

Manual memory int* ptr{new int{5}}; *ptr = 7; delete ptr; ptr = nullptr;

ptr

slide-71
SLIDE 71

39 / 82

Pointers

Manual memory

‚ A pointer doesn’t have to point to a variable. ‚ You can place data inside the memory directly with new. ‚ This is called allocang data. ‚ When allocang memory it is your responsibility to destroy the object that lies in that memory. ‚ You can deallocate the memory by calling delete on the pointer.

slide-72
SLIDE 72

40 / 82

Pointers

Manual memory

‚ You can only deallocate memory that has been allocated (i.e. for every delete there must be a new). ‚ You can only delete memory once. ‚ Calling delete does not remove the pointer! ‚ Meaning the pointer will sll point to the memory address, but the object has been removed, so it points to nonsense.

slide-73
SLIDE 73

1 Classes 2 Pointers 3 List lab 4 Special Member Funcons

slide-74
SLIDE 74

42 / 82

List lab

‚ In lab 3 you are going to create a linked list. ‚ This is a list that consists of values that the user inserts. ‚ Each value is stored in a node which then points to the next value in the list. ‚ On the next slide is a simple implementaon of a node.

slide-75
SLIDE 75

43 / 82

List lab

Node struct Node { int value; Node* next; }; Node n2 {2, nullptr}; Node n1 {8, &n2}; Node* first {&n1};

slide-76
SLIDE 76

43 / 82

List lab

Node struct Node { int value; Node* next; }; Node n2 {2, nullptr}; Node n1 {8, &n2}; Node* first {&n1};

first value

8

next value

2

next

slide-77
SLIDE 77

43 / 82

List lab

Node struct Node { int value; Node* next; }; Node n2 {2, nullptr}; Node n1 {8, &n2}; Node* first {&n1};

first 8 2

slide-78
SLIDE 78

44 / 82

List lab

Node

‚ first points to whichever element is first in the list. ‚ Each Node then points to the next element in the list. ‚ Once the next pointer is nullptr we have reached the end of the list.

slide-79
SLIDE 79

45 / 82

List lab

Accessing data in Node Node n2 {2, nullptr}; Node n1 {8, &n2}; Node* first {&n1}; cout << (*first).value << endl;

slide-80
SLIDE 80

45 / 82

List lab

Accessing data in Node Node n2 {2, nullptr}; Node n1 {8, &n2}; Node* first {&n1}; cout << first->value << endl;

slide-81
SLIDE 81

46 / 82

List lab

Accessing data in Node

‚ You access data members in an object that a pointer points to by either: ‚ Dereferencing the pointer to get normal access ((*first).value), or ‚ Using the -> operator (first->value). ‚ These two ways are exactly the same. ‚ It is recommended to use ->, since it is easier on the eyes.

slide-82
SLIDE 82

47 / 82

List lab

List class List { public: // ... private: Node* first{}; };

slide-83
SLIDE 83

48 / 82

List lab

insert

class List { public: void remove(); void insert(int value) { Node* tmp{new Node{value}}; tmp->next = first; first = tmp; } private: Node* first{}; };

first

slide-84
SLIDE 84

48 / 82

List lab

insert

class List { public: void remove(); void insert(int value) { Node* tmp{new Node{value}}; tmp->next = first; first = tmp; } private: Node* first{}; };

first 9

slide-85
SLIDE 85

48 / 82

List lab

insert

class List { public: void remove(); void insert(int value) { Node* tmp{new Node{value}}; tmp->next = first; first = tmp; } private: Node* first{}; };

first 9 tmp

slide-86
SLIDE 86

48 / 82

List lab

insert

class List { public: void remove(); void insert(int value) { Node* tmp{new Node{value}}; tmp->next = first; first = tmp; } private: Node* first{}; };

first 9 tmp

slide-87
SLIDE 87

48 / 82

List lab

insert

class List { public: void remove(); void insert(int value) { Node* tmp{new Node{value}}; tmp->next = first; first = tmp; } private: Node* first{}; };

first 9 tmp

slide-88
SLIDE 88

48 / 82

List lab

insert

class List { public: void remove(); void insert(int value) { Node* tmp{new Node{value}}; tmp->next = first; first = tmp; } private: Node* first{}; };

first 9 4

slide-89
SLIDE 89

48 / 82

List lab

insert

class List { public: void remove(); void insert(int value) { Node* tmp{new Node{value}}; tmp->next = first; first = tmp; } private: Node* first{}; };

first 9 4 tmp

slide-90
SLIDE 90

48 / 82

List lab

insert

class List { public: void remove(); void insert(int value) { Node* tmp{new Node{value}}; tmp->next = first; first = tmp; } private: Node* first{}; };

first 9 4 tmp

slide-91
SLIDE 91

48 / 82

List lab

insert

class List { public: void remove(); void insert(int value) { Node* tmp{new Node{value}}; tmp->next = first; first = tmp; } private: Node* first{}; };

first 9 4 tmp

slide-92
SLIDE 92

48 / 82

List lab

insert

class List { public: void remove(); void insert(int value) { Node* tmp{new Node{value}}; tmp->next = first; first = tmp; } private: Node* first{}; };

first 9 4

slide-93
SLIDE 93

49 / 82

List lab

insert

‚ We have to allocate a new Node at inseron, why? ‚ If tmp is a normal variable, then it will disappear once the insert funcon has finished. ‚ But we want it to persist unl we want to remove it. ‚ Therefore we have to allocate nodes with new.

slide-94
SLIDE 94

50 / 82

List lab

A problem!

class List { public: void remove() { first = first->next; } void insert(int value); private: Node* first{}; };

first 9 4

slide-95
SLIDE 95

50 / 82

List lab

A problem!

class List { public: void remove() { first = first->next; } void insert(int value); private: Node* first{}; };

first 9 4

Remove

slide-96
SLIDE 96

50 / 82

List lab

A problem!

class List { public: void remove() { first = first->next; } void insert(int value); private: Node* first{}; };

first 9 4

slide-97
SLIDE 97

50 / 82

List lab

A problem!

class List { public: void remove() { first = first->next; } void insert(int value); private: Node* first{}; };

first 9 4

slide-98
SLIDE 98

50 / 82

List lab

A problem!

class List { public: void remove() { first = first->next; } void insert(int value); private: Node* first{}; };

first 9 4

Memory leak

slide-99
SLIDE 99

51 / 82

List lab

A problem!

‚ When removing a node it does not disappear by itself. ‚ Since we called new to create it, we have to call delete

  • n the node for it to actually disappear.

‚ The pointer that kept track of our memory got lost, meaning there is no way for us to access it again. ‚ If this is done repeatedly by our program our memory will slowly be filled up by these inaccessible objects. ‚ This type of problem is called memory leak.

slide-100
SLIDE 100

52 / 82

List lab

Let’s try again!

class List { public: void remove() { Node* tmp = first; first = first->next; delete tmp; } void insert(int value); private: Node* first{}; };

first 9 4

slide-101
SLIDE 101

52 / 82

List lab

Let’s try again!

class List { public: void remove() { Node* tmp = first; first = first->next; delete tmp; } void insert(int value); private: Node* first{}; };

first 9 4

Remove

slide-102
SLIDE 102

52 / 82

List lab

Let’s try again!

class List { public: void remove() { Node* tmp = first; first = first->next; delete tmp; } void insert(int value); private: Node* first{}; };

first 9 4 tmp

slide-103
SLIDE 103

52 / 82

List lab

Let’s try again!

class List { public: void remove() { Node* tmp = first; first = first->next; delete tmp; } void insert(int value); private: Node* first{}; };

first 9 4 tmp

slide-104
SLIDE 104

52 / 82

List lab

Let’s try again!

class List { public: void remove() { Node* tmp = first; first = first->next; delete tmp; } void insert(int value); private: Node* first{}; };

first 9 tmp

slide-105
SLIDE 105

52 / 82

List lab

Let’s try again!

class List { public: void remove() { Node* tmp = first; first = first->next; delete tmp; } void insert(int value); private: Node* first{}; };

first 9

slide-106
SLIDE 106

53 / 82

List lab

Let’s try again!

‚ Now we can insert and remove values correctly in our list without any memory leaks. ‚ This was done because we delete the node that gets removed, thus giving that memory back to the

  • perang system.

‚ But there is sll a problem... What happens when the list is destroyed? ‚ Then everything will leak since we haven’t called

delete on the nodes that are le.

slide-107
SLIDE 107

1 Classes 2 Pointers 3 List lab 4 Special Member Funcons

slide-108
SLIDE 108

55 / 82

Special Member Funcons

Destructor

class List { public: List() // constructor : first{nullptr} { } ~List() // destructor { // go through each node in our list and call delete on them } void remove(); void insert(int value); private: Node* first{}; };

slide-109
SLIDE 109

56 / 82

Special Member Funcons

Destructor

‚ The constructor gets called when an object is created, ‚ There is a related funcon we can create called the destructor. ‚ The destructor is instead called when the object is destroyed. ‚ In the destructor we should remove anything that doesn’t get removed by itself. ‚ The destructor has the same name as the class, but with a ~ added to the start.

slide-110
SLIDE 110

57 / 82

Special Member Funcons

Constructors & destructors

{ List my_list{}; // the constructor is called // do things with the list } // the destructor is called

slide-111
SLIDE 111

58 / 82

Special Member Funcons

Constructors & destructors

‚ When a List is created the constructor is called. ‚ Once the List falls out of scope, the destructor is called (this happens when the variable is destroyed).

slide-112
SLIDE 112

59 / 82

Special Member Funcons

Copies

int main() { List my_list{}; my_list.insert(5); my_list.insert(2); { // copy my_list into copy List copy {my_list}; } }

first my_list first copy 2 5

slide-113
SLIDE 113

59 / 82

Special Member Funcons

Copies

int main() { List my_list{}; my_list.insert(5); my_list.insert(2); { // copy my_list into copy List copy {my_list}; } }

first my_list first copy 2 5

slide-114
SLIDE 114

59 / 82

Special Member Funcons

Copies

int main() { List my_list{}; my_list.insert(5); my_list.insert(2); { // copy my_list into copy List copy {my_list}; } }

first my_list

slide-115
SLIDE 115

59 / 82

Special Member Funcons

Copies

int main() { List my_list{}; my_list.insert(5); my_list.insert(2); { // copy my_list into copy List copy {my_list}; } }

first my_list

slide-116
SLIDE 116

59 / 82

Special Member Funcons

Copies

int main() { List my_list{}; my_list.insert(5); my_list.insert(2); { // copy my_list into copy List copy {my_list}; } }

first my_list

Already removed

slide-117
SLIDE 117

60 / 82

Special Member Funcons

Copies

‚ We can copy objects in C++ and our list is no excepon. ‚ The compiler doesn’t understand how to properly copy

  • ur list.

‚ It will simply say that they point to exactly the same lists. ‚ This happens because the compiler will just copy the

first pointer, not its content.

‚ This is called a shallow copy.

slide-118
SLIDE 118

61 / 82

Special Member Funcons

Deep copies

first my_list 2 5 first copy

slide-119
SLIDE 119

61 / 82

Special Member Funcons

Deep copies

first my_list 2 5 first copy 2

slide-120
SLIDE 120

61 / 82

Special Member Funcons

Deep copies

first my_list 2 5 first copy 2 5

slide-121
SLIDE 121

62 / 82

Special Member Funcons

Deep copies

‚ A deep copy is when we copy everything, not just the pointers. ‚ In this parcular case it is when we copy each node in

my_list into copy (in the same order).

slide-122
SLIDE 122

63 / 82

Special Member Funcons

Copy constructor

class List { public: List(); // default constructor List(List const& other) { // perform a deep copy of the lists } ~List(); // destructor void remove(); void insert(int value); private: Node* first{}; };

slide-123
SLIDE 123

64 / 82

Special Member Funcons

Copy constructor

‚ A copy constructor is a special constructor that tells the compiler how it is supposed to copy our class. ‚ It is the constructor that takes an object of the same class as a const&. ‚ The compile calls this constructor whenever it wants to copy an object of your class.

slide-124
SLIDE 124

65 / 82

Special Member Funcons

Copy assignment List my_list{}; my_list.insert(5); my_list.insert(2); List copy{}; copy.insert(1); copy.insert(4); // copy assignment copy = my_list;

slide-125
SLIDE 125

66 / 82

Special Member Funcons

Copy assignment

‚ Copy assignment is how we copy objects into each

  • ther aer they have been created.

‚ They suffer from the same problem as the copy constructor; ‚ namely that they have to perform a deep copy, which the compiler doesn’t know how to do. ‚ But they suffer from one other problem...

slide-126
SLIDE 126

67 / 82

Special Member Funcons

Copy assignment

first my_list 2 5 first copy 4 1

slide-127
SLIDE 127

67 / 82

Special Member Funcons

Copy assignment

first my_list 2 5 first copy 4 1 2 5

slide-128
SLIDE 128

67 / 82

Special Member Funcons

Copy assignment

first my_list 2 5 first copy 4 1 2 5

slide-129
SLIDE 129

67 / 82

Special Member Funcons

Copy assignment

first my_list 2 5 first copy 4 1 2 5

Memory leak

slide-130
SLIDE 130

67 / 82

Special Member Funcons

Copy assignment

first my_list 2 5 first copy

slide-131
SLIDE 131

68 / 82

Special Member Funcons

Copy assignment

‚ The list we are copying to might already contain elements. ‚ If just perform a deep copy than the previous elements will be lost (i.e. we get a memory leak). ‚ This is a big problem. So when doing copy assignment, we have to make sure that we remove the previous elements.

slide-132
SLIDE 132

69 / 82

Special Member Funcons

Copy assignment

first my_list 2 5 first copy 4 1

slide-133
SLIDE 133

69 / 82

Special Member Funcons

Copy assignment

first my_list 2 5 first copy 4 1 2 5

slide-134
SLIDE 134

69 / 82

Special Member Funcons

Copy assignment

first my_list 2 5 first copy 2 5

slide-135
SLIDE 135

69 / 82

Special Member Funcons

Copy assignment

first my_list 2 5 first copy 2 5

slide-136
SLIDE 136

70 / 82

Special Member Funcons

Copy assignment operator

class List { public: List(); // default constructor List(List const& other); // copy constructor ~List(); // destructor List& operator=(List const& other) { // remove previous list and deep copy other return *this; } // ... };

slide-137
SLIDE 137

71 / 82

Special Member Funcons

Copy assignment operator

‚ The copy assignment operator is a special operator

  • verload that allows us to specify what happens during

copy assignment. ‚ This operator must be declared inside the class. ‚ It must also return a reference to the list that was just assigned to. ‚ This is done by returning *this. ‚ Here we dereference this which is a pointer to the

  • bject we are inside right now.
slide-138
SLIDE 138

72 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list

slide-139
SLIDE 139

72 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first list

slide-140
SLIDE 140

72 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first list 3 5

slide-141
SLIDE 141

72 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first list 3 5 first

slide-142
SLIDE 142

72 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first list 3 5 first 3 5

slide-143
SLIDE 143

72 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first list first 3 5

slide-144
SLIDE 144

72 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first 3 5

slide-145
SLIDE 145

72 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first 3 5 3 5

slide-146
SLIDE 146

72 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first 3 5

slide-147
SLIDE 147

72 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list 3 5

slide-148
SLIDE 148

73 / 82

Special Member Funcons

Temporary objects

‚ Inside get_list we create a new List object. ‚ Then we return it as a copy. ‚ The object we return is temporary. ‚ We then copy that temporary object into my_list. ‚ There are a lot of copies being made here...

slide-149
SLIDE 149

74 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list

slide-150
SLIDE 150

74 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first list

slide-151
SLIDE 151

74 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first list 3 5

slide-152
SLIDE 152

74 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first list 3 5 first

slide-153
SLIDE 153

74 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first list 3 5 first

slide-154
SLIDE 154

74 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list first list 3 5 first

slide-155
SLIDE 155

74 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list 3 5 first

slide-156
SLIDE 156

74 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list 3 5 first

slide-157
SLIDE 157

74 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list 3 5 first

slide-158
SLIDE 158

74 / 82

Special Member Funcons

Temporary objects

List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list {get_list()};

first my_list 3 5

slide-159
SLIDE 159

75 / 82

Special Member Funcons

Temporary objects

‚ In C++ there is a way to reduce these copies. ‚ We could just steal the content from the temporary list by changing the pointers. ‚ Make sure to set the temporary first pointer to

nullptr since othewise the destructor of the

temporary list will remove the content. ‚ This is called move; we move memory from one object to another.

slide-160
SLIDE 160

76 / 82

Special Member Funcons

Temporary objects

‚ The compiler knows when you are trying to copy temporary objects. ‚ So it would be nice if we could tell the compiler how to perform these move operaons. ‚ We can introduce something called a Move constructor to tell the compiler how we perform a move.

slide-161
SLIDE 161

77 / 82

Special Member Funcons

Move constructor

class List { public: List(); // default constructor List(List const& other); // copy constructor List(List&& other) { // perform the move by shuffling the first pointers } ~List(); // destructor List& operator=(List const& other); // copy assignment operator // ... };

slide-162
SLIDE 162

78 / 82

Special Member Funcons

Move assignment List get_list() { List list{}; list.insert(5); list.insert(3); return list; } List my_list{}; my_list.insert(4); my_list.insert(2); my_list = get_list();

slide-163
SLIDE 163

79 / 82

Special Member Funcons

Move assignment operator

class List { public: List(); // default constructor List(List const& other); // copy constructor List(List&& other); // move constructor ~List(); // destructor List& operator=(List const& other); // copy assignment operator List& operator=(List&& other) { // remove old content of the list // move content from other to this object } // ... };

slide-164
SLIDE 164

80 / 82

Special Member Funcons

Special Member Funcons

class List { public: List(); // default constructor List(List const& other); // copy constructor List(List&& other); // move constructor ~List(); // destructor List& operator=(List const& other); // copy assignment operator List& operator=(List&& other); // move assignment operator // ... };

slide-165
SLIDE 165

81 / 82

Special Member Funcons

Nice inializaon List list1 {1, 2, 3}; List list2 {4, 5}; List list3 {6, 7, 8, 9};

#include <initializer_list> class List { public: List(std::initializer_list<int> list) { for (int i : list) { insert(i); } } };

slide-166
SLIDE 166

82 / 82

Special Member Funcons

Nice inializaon

‚ It is possible to create a special constructor that takes an arbitrary amount of values. ‚ These values must all share the same type. ‚ This is done by creang a constructor that takes

std::initializer_list as argument.

‚ To go through the inializer list you must use a special type of for-loop, we will talk more about it later. For now, just know that it iterates through the list and places the current value inside the variable i. ‚ This type of loop is called a range-based for-loop.

slide-167
SLIDE 167

www.liu.se