CS 144 Advanced C++ Programming April 30 Class Meeting

Slides:



Advertisements
Similar presentations
Constructor. 2 constructor The main use of constructors is to initialize objects. A constructor is a special member function, whose name is same as class.
Advertisements

Data Structures Using C++1 Chapter 3 Pointers and Array-Based Lists.
Introduction to Programming Lecture 39. Copy Constructor.
6/10/2015C++ for Java Programmers1 Pointers and References Timothy Budd.
 2006 Pearson Education, Inc. All rights reserved Operator Overloading.
1 Pointers, Dynamic Data, and Reference Types Review on Pointers Reference Variables Dynamic Memory Allocation –The new operator –The delete operator –Dynamic.
Shallow Versus Deep Copy and Pointers Shallow copy: when two or more pointers of the same types point to the same memory – They point to the same data.
Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes
 2006 Pearson Education, Inc. All rights reserved Classes: A Deeper Look.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 19 Clicker Questions November 3, 2009.
Pointer Data Type and Pointer Variables
 2006 Pearson Education, Inc. All rights reserved Classes: A Deeper Look, Part 2.
CS212: Object Oriented Analysis and Design Lecture 7: Arrays, Pointers and Dynamic Memory Allocation.
1 Overloading Overloading allows a function or operator to have a different meaning depending on the type of objects it is used on. Examples: operator+
1 Chapter 15-2 Pointers, Dynamic Data, and Reference Types Dale/Weems.
Pointers and Dynamic Memory Allocation Copyright Kip Irvine 2003, all rights reserved. Revised 10/28/2003.
Dynamically Allocated Arrays December 4, Skip the Rest of this PowerPoint.
Chapter 12: Pointers, Classes, Virtual Functions, and Abstract Classes.
Object Oriented Programming Elhanan Borenstein Lecture #3 copyrights © Elhanan Borenstein.
CS 376b Introduction to Computer Vision 01 / 23 / 2008 Instructor: Michael Eckmann.
EEL 3801 C++ as an Enhancement of C. EEL 3801 – Lotzi Bölöni Comments  Can be done with // at the start of the commented line.  The end-of-line terminates.
Chapter 1 C++ Basics Review (Section 1.4). Classes Defines the organization of a data user-defined type. Members can be  Data  Functions/Methods Information.
1 Chapter 15-1 Pointers, Dynamic Data, and Reference Types Dale/Weems.
Chapter 12: Pointers, Classes, Virtual Functions, Abstract Classes, and Lists.
Yan Shi CS/SE 2630 Lecture Notes
Constructors and Destructors
Pointers and Dynamic Arrays
CMPE Data Structures and Algorithms in C++ September 14 Class Meeting
Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes
CISC181 Introduction to Computer Science Dr
CMPE 135: Object-Oriented Analysis and Design October 17 Class Meeting
Pointers Revisited What is variable address, name, value?
CMPE 180A Data Structures and Algorithms in C++ February 15 Class Meeting Department of Computer Engineering San Jose State University Spring 2018 Instructor:
Pointers and References
This pointer, Dynamic memory allocation, Constructors and Destructor
Dynamic Memory Review what is static, automatic, dynamic variables? why are dynamic(ally allocated) variables needed what is program stack? function.
Dynamically Allocated Memory
Dynamic Memory Allocation
Chapter 12: Pointers, Classes, Virtual Functions, and Abstract Classes
Object Oriented Programming COP3330 / CGS5409
Classes with Dynamically Allocated Data
Chapter 10: Pointers Starting Out with C++ Early Objects Ninth Edition
Chapter 15 Pointers, Dynamic Data, and Reference Types
Chapter 9: Pointers.
Pointers, Dynamic Data, and Reference Types
Constant pointers and pointers to constants
Chapter 15 Pointers, Dynamic Data, and Reference Types
Constructors and destructors
Constructors and Destructors
CMPE 135: Object-Oriented Analysis and Design November 27 Class Meeting Department of Computer Engineering San Jose State University Fall 2018 Instructor:
CS148 Introduction to Programming II
9-10 Classes: A Deeper Look.
C++ Pointers and Strings
CS 144 Advanced C++ Programming February 12 Class Meeting
Operator Overloading; String and Array Objects
CS 144 Advanced C++ Programming February 12 Class Meeting
Move Semantics CSCE 121.
CS 144 Advanced C++ Programming February 21 Class Meeting
Introduction to Data Structures and Software Engineering
CS 144 Advanced C++ Programming April 25 Class Meeting
CS 144 Advanced C++ Programming March 21 Class Meeting
C++ Pointers and Strings
Pointers, Dynamic Data, and Reference Types
CS 144 Advanced C++ Programming April 30 Class Meeting
9-10 Classes: A Deeper Look.
CS 144 Advanced C++ Programming May 9 Class Meeting
Copy Constructors and Overloaded Assignment
CMPE 152: Compiler Design May 2 Class Meeting
SPL – PS3 C++ Classes.
SPL – PS2 C++ Memory Handling.
Presentation transcript:

CS 144 Advanced C++ Programming April 30 Class Meeting Department of Computer Engineering San Jose State University Spring 2019 Instructor: Ron Mak www.cs.sjsu.edu/~mak

Unofficial Field Trip Computer History Museum in Mt. View http://www.computerhistory.org/ Provide your own transportation to the museum. Saturday, May 4, 11:30 – closing time Special free admission. We will meet in the lobby. No backpacks. Experience a fully restored IBM 1401 mainframe computer from the early 1960s in operation. Do a self-guided tour of the Revolution exhibit.

Pointers vs. References The value of a pointer variable is the address of another variable. Pointer variable p1 contains the address of variable i. Pointer variable p2 contains the address of the dynamically allocated Birthday object. A reference variable is an alias for an already existing variable. Both r1 and i now refer to the same variable. int i, j; int *p1 = &i; Birthday *p2 = new Birthday(1963, 9, 2); int& r1 = i;

Pointers vs. References, cont’d Both pointers and references are implemented as addresses, but there are major differences. A pointer variable can be reassigned: A reference variable must be assigned at initialization and then cannot be reassigned. A pointer variable can be null. A reference variable can only be an alias for another variable. p1 = &j; p2 = new Birthday(1967, 4, 3); int& r1 = i; p2 = nullptr;

Pointers vs. References, cont’d Explicitly dereference a pointer variable. A reference variable is implicitly dereferenced. A pointer variable’s value can participate in address arithmetic. A reference variable’s address value cannot. A reference variable is similar to a constant pointer. int k, y; k = *p; y = p2->year; Birthday bd(1960, 9, 2); Birthday& rbd = bd; rbd.year = 1964;

Use of References When you declare a function’s parameter to be a reference, you are saying that the parameter is an alias of the caller’s argument. Example: Function parameter parm is an alias for the caller’s argument k. Therefore, any changes to parm in the function changes k instantaneously, because they are the same variable. void func(int& parm) ... ... func(k);

Use of References, cont’d A function can return a reference. Example: Special variable this is a pointer to the object, and therefore *this is the object itself. We are returning an alias to the object. SafeArray& SafeArray::operator =(const SafeArray& rhs) { ... return *this; }

Use of References, cont’d You can pass a pointer by reference. The syntax is a bit awkward. Example: or: or: Note the order of the * and the &. void func(int* &ptr); void func(int*& ptr); void func(int *&ptr);

Use of References, cont’d The overridden assignment operator should return a reference so that in a chained assignment like would work. Recall the signature of a copy constructor. The assignment operator is right associative. is executed as a = b = c; MyClass(const MyClass& other) a = b = c; a = (b = c);

Deep Copy If you want a deep copy, one that includes copying the data, you need to write your own copy constructor. BirthdayDeepCopy/BirthdayDynamic.cpp BirthdayDynamic::BirthdayDynamic(const BirthdayDynamic& other)     : length(other.length), elements(new Birthday[length]) {     // Copy the elements.     for (int i = 0; i < length; i++) elements[i] = other[i]; } Create dynamic birthday array: Print dynamic birthday array: 0/0/0 9/2/1981 5/8/1992 End of program!

Problems with a Standard (“Raw”) Pointer A raw pointer’s declaration doesn’t indicate whether: It “owns” the object that points to (should you delete the object?) It points to a single object or to an array (should you call delete or delete[]?) Should you call a dedicated destructor function? Will you delete the object exactly once? Memory leak if you never delete the object. Segmentation fault if you delete the object more than once.

Raw Pointers vs. Smart Pointers Raw pointers are powerful but dangerous. Use a smart pointer instead. Unique pointer Has exclusive ownership of the object it points to. The ownership can be transferred. The object is automatically deleted when the pointer goes out of scope. Shared pointer Multiple pointers can point to the same object. The object is deleted only once.

Unique Pointer Exclusive ownership of the object. An object can have at most one unique pointer at a time pointing to it. Ownership can be transferred to another unique pointer. The source pointer is automatically set to null. When the owning pointer is set to point to another object, or goes out of scope, the object it points to is automatically deleted.

Unique Pointer Example We’ll use our old Birthday class. The default constructor, constructor, and destructor each writes a message when it’s called. TestUnique.cpp int main() {     cout << "raw_ptr ..." << endl;     Birthday *raw_ptr = new Birthday(2001, 1, 1);     cout << "*raw_ptr   = " << *raw_ptr   << endl;     cout << endl << "uniq_ptr1 and uniq_ptr2 ..." << endl;     unique_ptr<Birthday> uniq_ptr1(new Birthday(2002, 2, 2));     unique_ptr<Birthday> uniq_ptr2(nullptr);     cout << "*uniq_ptr1 = " << *uniq_ptr1 << endl; ... raw_ptr ... *** Constructor called for 1/1/2001 *raw_ptr   = 1/1/2001 uniq_ptr1 and uniq_ptr2 ... *** Constructor called for 2/2/2002 *uniq_ptr1 = 2/2/2002

Unique Pointer Example, cont’d “Move” the object from one pointer to another. Can’t copy, because of exclusive ownership. The source pointer is automatically set to nullptr.     cout << endl << "uniq_ptr2 = move(uniq_ptr1) ..." << endl;     uniq_ptr2 = move(uniq_ptr1);     if (uniq_ptr1 == nullptr) cout << "uniq_ptr1 is null" << endl;     else                      cout << "*uniq_ptr1 = " << *uniq_ptr1 << endl;     cout << "*uniq_ptr2 = " << *uniq_ptr2 << endl; uniq_ptr2 = move(uniq_ptr1) ... uniq_ptr1 is null *uniq_ptr2 = 2/2/2002

Unique Pointer Example, cont’d You can associate a custom destructor with a unique pointer. In this example, we use a lambda expression. Also note the use of decltype.     function<void(Birthday *bptr)> delete_birthday = [] (Birthday *ptr)     {         cout << "Deleting " << *ptr << endl;         delete ptr;     };     cout << endl << "uniq_ptr3 ..." << endl;     unique_ptr<Birthday, decltype(delete_birthday)>         uniq_ptr3(new Birthday(2003, 3, 3), delete_birthday);     cout << "*uniq_ptr3 = " << *uniq_ptr3 << endl; uniq_ptr3 ... *** Constructor called for 3/3/2003 *uniq_ptr3 = 3/3/2003

Unique Pointer Example, cont’d Use the reset member function to change the value of a unique pointer.     cout << endl << "uniq_ptr4 ..." << endl;     unique_ptr<Birthday> uniq_ptr4(nullptr);     uniq_ptr4.reset(new Birthday(2004, 4, 4));     cout << "*uniq_ptr4 = " << *uniq_ptr4 << endl;     cout << endl << "uniq_ptr4.reset ..." << endl;     uniq_ptr4.reset(new Birthday(2005, 5, 5)); uniq_ptr4 ... *** Constructor called for 4/4/2004 *uniq_ptr4 = 4/4/2004 uniq_ptr4.reset ... *** Constructor called for 5/5/2005 *** Destructor called for 4/4/2004 *uniq_ptr4 = 5/5/2005

Unique Pointer Example, cont’d When a unique smart pointer goes out of scope, the object it points to is automatically removed from memory.     cout << endl << "Program termination ..." << endl;     return 0; } Program termination ... *** Destructor called for 5/5/2005 Deleting 3/3/2003 *** Destructor called for 3/3/2003 *** Destructor called for 2/2/2002 Memory leak! Birthday *raw_ptr = new Birthday(2001, 1, 1);

Shared Pointer Multiple shared smart pointers can point at the same time to a single object. Shared-ownership resource management. When the last pointer no longer points to the object, the object is automatically deleted. It is deleted only once. Uses reference counts.

Shared Pointer Example int main() {     cout << endl << "shar_ptr1 and shar_ptr2 ..." << endl;     shared_ptr<Birthday> shar_ptr1(new Birthday(2001, 1, 1));     shared_ptr<Birthday> shar_ptr2(shar_ptr1);     cout << "*shar_ptr1 = " << *shar_ptr1 << endl;     cout << "*shar_ptr2 = " << *shar_ptr2 << endl;     {         cout << endl << "Entering new scope!" << endl;         shared_ptr<Birthday> shar_ptr3(shar_ptr2);         shared_ptr<Birthday> shar_ptr4(shar_ptr3);         cout << "*shar_ptr1 = " << *shar_ptr1 << endl;         cout << "*shar_ptr2 = " << *shar_ptr2 << endl;         cout << "*shar_ptr3 = " << *shar_ptr3 << endl;         cout << "*shar_ptr4 = " << *shar_ptr4 << endl;         cout << "Exiting scope!" << endl << endl;     }     cout << endl << "Program termination ..." << endl;     return 0; } TestShared.cpp Nested scope

Shared Pointer Example, cont’d int main() {     cout << "shar_ptr1 and shar_ptr2 ..." << endl;     shared_ptr<Birthday> shar_ptr1(new Birthday(2001, 1, 1));     shared_ptr<Birthday> shar_ptr2(shar_ptr1);     cout << "*shar_ptr1 = " << *shar_ptr1 << endl;     cout << "*shar_ptr2 = " << *shar_ptr2 << endl; shar_ptr1 and shar_ptr2 ... *** Constructor called for 1/1/2001 *shar_ptr1 = 1/1/2001 *shar_ptr2 = 1/1/2001

Shared Pointer Example, cont’d     {         cout << endl << "Entering new scope!" << endl;         shared_ptr<Birthday> shar_ptr3(shar_ptr2);         shared_ptr<Birthday> shar_ptr4(shar_ptr3);         cout << "*shar_ptr1 = " << *shar_ptr1 << endl;         cout << "*shar_ptr2 = " << *shar_ptr2 << endl;         cout << "*shar_ptr3 = " << *shar_ptr3 << endl;         cout << "*shar_ptr4 = " << *shar_ptr4 << endl;         cout << "Exiting scope!" << endl << endl;     } Entering new scope! *shar_ptr1 = 1/1/2001 *shar_ptr2 = 1/1/2001 *shar_ptr3 = 1/1/2001 *shar_ptr4 = 1/1/2001 Exiting scope! Nothing special happens when we exit the scope. shar_ptr3 and shar_ptr4 go out of scope.

Shared Pointer Example, cont’d     cout << "*shar_ptr2 = " << *shar_ptr2 << endl;     cout << endl << "Program termination ..." << endl;     return 0; *shar_ptr2 = 1/1/2001 Program termination ... *** Destructor called for 1/1/2001 The destructor is automatically called once the last pointer to the object goes out of scope.

Shared Pointer Implementation Effective Modern C++ by Scott Meyers O’Reilly, 2015 ISBN 978-1-491-90399-5

Introduction to Move Semantics As we’ve seen, excessive calls to the copy constructor can hurt performance. In a move from source to target, instead of copying a resource, the target “steals” the resource from the source. The source contains a pointer to an object. The target gets a copy of the pointer. The source’s pointer is set to null. Therefore, the target has taken ownership of the object.

Introduction to Move Semantics, cont’d Move semantics involve lvalues and rvalues. An lvalue is an object. So called because it can appear on the left side of an assignment statement (i.e., it can be an assignment target). An rvalue is a temporary value or a value not associated with an object. So called because it can be a value that’s calculated on the right side of an assignment statement.

Introduction to Move Semantics, cont’d When an rvalue is assigned in an assignment statement, or when an rvalue is passed by value to a function, a copy is made of the value. But it is wasteful to copy a temporary value. That value normally is about to disappear. Move semantics allows us to use that temporary value by taking ownership of its resources. Reduce the amount of runtime copying.

Move Semantics Example Message.h class Message { private:     int length;     char *text;      public:     Message() : length(0), text(nullptr) {}     Message(char *t) : length(strlen(t)), text(t) {}     virtual ~Message()     {         if (length > 0) delete[] text;         length = 0;         text = nullptr;     }

Move Semantics Example, cont’d     Message(const Message& other)     {         cout << "*** Copy constructor called!" << endl;         length = other.length;         text = new char[length + 1];         strcpy(text, other.text);     }     Message(Message&& other)         cout << "*** Move constructor called!" << endl;         text = other.text;         other.length = 0;         other.text = nullptr; Copy constructor Copy the source’s data. Move constructor Steal the source’s data without copying it.

Move Semantics Example, cont’d Message& operator =(const Message& other) {     cout << "*** Copy assignment called!" << endl;     if (this != &other)     {         if (length > 0) delete[] text;         length = other.length;         text = new char[length + 1];         strcpy(text, other.text);     }     return *this; } Copy assignment Message& operator =(Message&& other) {     cout << "*** Move assignment called!" << endl;     if (this != &other)     {         if (length > 0) delete[] text;         length = other.length;         text = other.text;                      other.length = 0;         other.text = nullptr;     }     return *this; } Move assignment Steal the source’s data without copying it.

Move Semantics Example, cont’d friend ostream& operator <<(ostream& outs, const Message& msg) {     cout << msg.length << ":";     if (msg.text != nullptr) cout << msg.text;     else                     cout << "<empty>";     return outs; }

Move Semantics Example, cont’d TestMove.cpp char h[16], w[16]; strcpy(h, "hello"); strcpy(w, "world"); cout << "h = " << h << endl; cout << "w = " << w << endl; cout << endl << "Default constructor:" << endl; Message msg; cout << "msg = " << msg << endl; cout << endl << "Regular constructor:" << endl; Message hello1(h); Message world1(w); cout << "hello1 = " << hello1 << endl; cout << "world1 = " << world1 << endl; h = hello w = world Default constructor: msg = 0:<empty> Regular constructor: hello1 = 5:hello world1 = 5:world

Move Semantics Example, cont’d cout << endl << "Copy constructor:" << endl; Message hello2(hello1); cout << "hello1 = " << hello1 << endl; cout << "hello2 = " << hello2 << endl; cout << endl << "Overloaded copy assignment operator:" << endl; Message world2; world2 = world1; cout << "world1 = " << world1 << endl; cout << "world2 = " << world2 << endl; Copy constructor: *** Copy constructor called! hello1 = 5:hello hello2 = 5:hello Overloaded copy assignment operator: *** Copy assignment called! world1 = 5:world world2 = 5:world

Move Semantics Example, cont’d cout << endl << "Move constructor:" << endl; Message hello3(move(hello1)); cout << "hello1 = " << hello1 << endl; cout << "hello3 = " << hello3 << endl; cout << endl << "Overloaded move assignment operator:" << endl; Message world3; world3 = move(world1); cout << "world1 = " << world1 << endl; cout << "world3 = " << world3 << endl; Move constructor: *** Move constructor called! hello1 = 0:<empty> hello3 = 5:hello Overloaded move assignment operator: *** Move assignment called! world1 = 0:<empty> world3 = 5:world

Review: Rule of the “Big Three” If a class defines one or more of the following, it should explicitly define all three: Destructor Copy constructor Copy assignment operator The copy constructor and the copy assignment operator each does a deep copy.

Rule of the “Big Five” Explicitly define: Destructor Copy constructor Copy assignment operator Move constructor Move assignment operator The move constructor and the move assignment operator can each steal resources from temporary source objects.