The C++ Object Lifecycle. EECS 211 Winter 2019

Similar documents
Dynamic memory. EECS 211 Winter 2019

Linked data structures. EECS 211 Winter 2019

CSC 1600 Memory Layout for Unix Processes"

Common Misunderstandings from Exam 1 Material

Pointers, Dynamic Data, and Reference Types

In Java we have the keyword null, which is the value of an uninitialized reference type

o Code, executable, and process o Main memory vs. virtual memory

Implementing Abstractions

An Introduction to C++

The issues. Programming in C++ Common storage modes. Static storage in C++ Session 8 Memory Management

Intermediate Programming, Spring 2017*

Vector and Free Store (Vectors and Arrays)

Discussion 1E. Jie(Jay) Wang Week 10 Dec.2

Intermediate Programming, Spring 2017*

Chapter 17: Linked Lists

Dynamic Memory: Alignment and Fragmentation

Vector and Free Store (Pointers and Memory Allocation)

Creating a String Data Type in C

Assignment of Objects

CS201 Some Important Definitions

CS32 - Week 1. Umut Oztok. June 24, Umut Oztok CS32 - Week 1

Memory (Stack and Heap)

CA341 - Comparative Programming Languages

11 'e' 'x' 'e' 'm' 'p' 'l' 'i' 'f' 'i' 'e' 'd' bool equal(const unsigned char pstr[], const char *cstr) {

Lecture 8 Dynamic Memory Allocation

cout << "How many numbers would you like to type? "; cin >> memsize; p = new int[memsize];

l Determine if a number is odd or even l Determine if a number/character is in a range - 1 to 10 (inclusive) - between a and z (inclusive)

Containers: Stack. Jordi Cortadella and Jordi Petit Department of Computer Science

Containers: Stack. The Stack ADT. The Stack ADT. The Stack ADT

Advanced Systems Programming

Announcements. Lecture 05a Header Classes. Midterm Format. Midterm Questions. More Midterm Stuff 9/19/17. Memory Management Strategy #0 (Review)

Kurt Schmidt. October 30, 2018

04-17 Discussion Notes

cc -o build/test_translate build/test_translate.o b... $

CSC212 Data Structure - Section FG

A linear-list Data Structure where - addition of elements to and - removal of elements from are restricted to the first element of the list.

CPSC 427: Object-Oriented Programming

CS201- Introduction to Programming Current Quizzes

However, in C we can group related variables together into something called a struct.

double d0, d1, d2, d3; double * dp = new double[4]; double da[4];

G52CPP C++ Programming Lecture 10. Dr Jason Atkin

Chapter 17: Linked Lists

Week 9 Part 1. Kyle Dewey. Tuesday, August 28, 12

CSCI 2212: Intermediate Programming / C Storage Class and Dynamic Allocation

Overview of C++: Part 1

1d: tests knowing about bitwise fields and union/struct differences.

CS 222: Pointers and Manual Memory Management

C++ Addendum: Inheritance of Special Member Functions. Constructors Destructor Construction and Destruction Order Assignment Operator

Run Time Environment

C++ PROGRAMMING LANGUAGE: DYNAMIC MEMORY ALLOCATION AND EXCEPTION IN C++. CAAM 519, CHAPTER 15

Low-Level C Programming. Memory map Pointers Arrays Structures

CS11 Advanced C++ Spring 2018 Lecture 2

a data type is Types

Cpt S 122 Data Structures. Data Structures

QUIZ. What is wrong with this code that uses default arguments?

DAY 3. CS3600, Northeastern University. Alan Mislove

Dynamic Memory Allocation

Intermediate Programming, Spring 2017*

For instance, we can declare an array of five ints like this: int numbers[5];

! A data structure representing a list. ! A series of nodes chained together in sequence. ! A separate pointer (the head) points to the first

Memory Management I. two kinds of memory: stack and heap

C++ Programming Lecture 4 Software Engineering Group

CS 61C: Great Ideas in Computer Architecture C Memory Management, Usage Models

CSE 374 Programming Concepts & Tools. Hal Perkins Spring 2010

CprE 288 Introduction to Embedded Systems Exam 1 Review. 1

Heap Arrays and Linked Lists. Steven R. Bagley

September 10,

CMPS 105 Systems Programming. Prof. Darrell Long E2.371

A brief introduction to C++

CS107, Lecture 9 C Generics Function Pointers

CSE 374 Programming Concepts & Tools. Hal Perkins Fall 2015 Lecture 19 Introduction to C++

CSE 143. Linked Lists. Linked Lists. Manipulating Nodes (1) Creating Nodes. Manipulating Nodes (3) Manipulating Nodes (2) CSE 143 1

Name: I. 20 II. 20 III. 20 IV. 40. CMSC 341 Section 01 Fall 2016 Data Structures Exam 1. Instructions: 1. This is a closed-book, closed-notes exam.

Object-Oriented Principles and Practice / C++

Recitation #11 Malloc Lab. November 7th, 2017

Reminder: compiling & linking

Memory and Pointers written by Cathy Saxton

Chapter 10. Pointers and Dynamic Arrays. Copyright 2016 Pearson, Inc. All rights reserved.

COMP 2355 Introduction to Systems Programming

CSCI-1200 Data Structures Spring 2018 Lecture 8 Templated Classes & Vector Implementation

Heap Arrays. Steven R. Bagley

Special Member Functions

Definition of Stack. 5 Linked Structures. Stack ADT Operations. ADT Stack Operations. A stack is a LIFO last in, first out structure.

CSE 333. Lecture 11 - constructor insanity. Hal Perkins Paul G. Allen School of Computer Science & Engineering University of Washington

CSE 333 Midterm Exam 5/9/14 Sample Solution

Classes in C++98 and C++11

Linked Lists 28/11/2018. Nodes with member functions. The need for a linked list class

Slide Set 14. for ENCM 339 Fall Steve Norman, PhD, PEng. Electrical & Computer Engineering Schulich School of Engineering University of Calgary

Understanding Pointers

Lecture 6 Dynamic Classes and the Law of the Big Three. Instructor: George Wolberg Department of Computer Science City College of New York

LECTURE 03 LINKED LIST

Class Vector: Interface CSE 143. Dynamic Memory In Classes [Chapter 4, p ] Vector Implementation. Many Ways to Implement. Draw the picture!

Object-Oriented Programming, Iouliia Skliarova

BBM 201 DATA STRUCTURES

University of Illinois at Urbana-Champaign Department of Computer Science. First Examination

CSCI 262 Data Structures. Arrays and Pointers. Arrays. Arrays and Pointers 2/6/2018 POINTER ARITHMETIC

Lecture Notes CPSC 122 (Fall 2014) Today Quiz 7 Doubly Linked Lists (Unsorted) List ADT Assignments Program 8 and Reading 6 out S.

Special Member Functions. Compiler-Generated Destructor. Compiler-Generated Default Constructor. Special Member Functions

HW 3: Malloc CS 162. Due: Monday, March 28, 2016

Questions: ECE551 PRACTICE Final

Transcription:

The C++ Object Lifecycle EECS 211 Winter 2019

2 Initial code setup $ cd eecs211 $ curl $URL211/lec/09lifecycle.tgz tar zx $ cd 09lifecycle

3 Road map Owned string type concept Faking it

An owned string type 4

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; };

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; The idea: data_ points to the string data (array of characters)

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; The idea: data_ points to the string data (array of characters) size_ is the actual number of characters in our string (we don t rely on '\0' termination anymore)

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; The idea: data_ points to the string data (array of characters) size_ is the actual number of characters in our string (we don t rely on '\0' termination anymore) capacity_ is the allocated size of data_, which might exceed size_, giving us space to grow

Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; The idea: data_ points to the string data (array of characters) size_ is the actual number of characters in our string (we don t rely on '\0' termination anymore) capacity_ is the allocated size of data_, which might exceed size_, giving us space to grow (We '\0'-terminate anyway to facilitate interaction with C but note also that internal '\0's will make C not see the whole string) 5

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; Invariants (must always be true for String s to be valid):

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; Invariants (must always be true for String s to be valid): 1. s.capacity_ == 0 if and only if s.data_ == nullptr

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; Invariants (must always be true for String s to be valid): 1. s.capacity_ == 0 if and only if s.data_ == nullptr 2. If s.capacity_ > 0 then:

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; Invariants (must always be true for String s to be valid): 1. s.capacity_ == 0 if and only if s.data_ == nullptr 2. If s.capacity_ > 0 then: 2.1 s.data_ points to a unique, free store allocated array of s.capacity_ chars

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; Invariants (must always be true for String s to be valid): 1. s.capacity_ == 0 if and only if s.data_ == nullptr 2. If s.capacity_ > 0 then: 2.1 s.data_ points to a unique, free store allocated array of s.capacity_ chars 2.2 s.size_ + 1 <= s.capacity_

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; Invariants (must always be true for String s to be valid): 1. s.capacity_ == 0 if and only if s.data_ == nullptr 2. If s.capacity_ > 0 then: 2.1 s.data_ points to a unique, free store allocated array of s.capacity_ chars 2.2 s.size_ + 1 <= s.capacity_ 2.3 s.data_[0],, s.data_[s.size_ - 1] are initialized

5 Our own String type This is C++: struct String char* data_; size_t size_, capacity_; }; Invariants (must always be true for String s to be valid): 1. s.capacity_ == 0 if and only if s.data_ == nullptr 2. If s.capacity_ > 0 then: 2.1 s.data_ points to a unique, free store allocated array of s.capacity_ chars 2.2 s.size_ + 1 <= s.capacity_ 2.3 s.data_[0],, s.data_[s.size_ - 1] are initialized 2.4 s.data_[s.size_] == '\0'

6 Some C++ stuff from the previous slide struct declarations create a type, so we can use String as a type, not just struct String The null pointer is named nullptr instead of NULL The C++ version of the heap is called the free store (and we will manage it using new and delete instead of malloc and free)

6 Some C++ stuff from the previous slide struct declarations create a type, so we can use String as a type, not just struct String The null pointer is named nullptr instead of NULL The C++ version of the heap is called the free store (and we will manage it using new and delete instead of malloc and free) (The old C ways still work, but we won t use them in C++. For example, we will see later why nullptr is better than NULL.)

7 The String type lifecycle The invariant says that the data_ member variable points to an object that is unique meaning that no other String s data_ points to the same object. Implications:

7 The String type lifecycle The invariant says that the data_ member variable points to an object that is unique meaning that no other String s data_ points to the same object. Implications: 1. To create a (non-empty) String, we need to allocate a new object for data_ to point to.

7 The String type lifecycle The invariant says that the data_ member variable points to an object that is unique meaning that no other String s data_ points to the same object. Implications: 1. To create a (non-empty) String, we need to allocate a new object for data_ to point to. 2. To copy-assign one String object to another, we need to copy the contents of data_, not the pointer data_ itself.

7 The String type lifecycle The invariant says that the data_ member variable points to an object that is unique meaning that no other String s data_ points to the same object. Implications: 1. To create a (non-empty) String, we need to allocate a new object for data_ to point to. 2. To copy-assign one String object to another, we need to copy the contents of data_, not the pointer data_ itself. 3. We need to delete (C++ s free) data_ each time we are done with a String object

7 The String type lifecycle The invariant says that the data_ member variable points to an object that is unique meaning that no other String s data_ points to the same object. Implications: 1. To create a (non-empty) String, we need to allocate a new object for data_ to point to. 2. To copy-assign one String object to another, we need to copy the contents of data_, not the pointer data_ itself. 3. We need to delete (C++ s free) data_ each time we are done with a String object C++ can do the above automatically for us, but we ll do it manually first

Faking it 8

9 Special functions C++ manages the lifecycle of an object with three kinds of special functions: Constructors initialize an uninitialized object Assignment operators copy or move from one initialized object to another The destructor frees an object s resources

9 Special functions C++ manages the lifecycle of an object with three kinds of special functions: Constructors initialize an uninitialized object Assignment operators copy or move from one initialized object to another The destructor frees an object s resources Our process for faking it: 1. Define an object 2. Call one constructor, once 3. Use the object for whatever 4. Call the destructor once 5. Don t use the object again after that

10 Object lifecycle state diagram operations constructor valid destructor uninitialized allocation deallocation defunct

10 Object lifecycle state diagram operations constructor valid destructor uninitialized allocation deallocation defunct C++ automatically constructs after allocation and destroys before deallocation, but first we re going to do it ourselves

11 DIY String constructors (1/2) // Constructs an empty string: void String_construct_default(String*); // Constructs by copying another String: void String_construct_copy(String*, const String* other); // Constructs by moving (stealing the resources // of) another String: void String_construct_move(String*, String* other);

11 DIY String constructors (1/2) // Constructs an empty string: void String_construct_default(String*); // Constructs by copying another String: void String_construct_copy(String*, const String* other); // Constructs by moving (stealing the resources // of) another String: void String_construct_move(String*, String* other); In C++ these three constructors will be special, in the sense that it uses them in particular places; for example, it uses the copy constructor every time you initialize a String from another String, which includes passing or returning by value.

12 DIY String constructors (2/2) We also want constructors that are specific to our String type: // Constructs from a C string: void String_construct_c_str(String*, const char* s); // Constructs from the range [begin, end): void String_construct_range(String*, const char* begin, const char* end);

13 DIY String destructor // Frees any resources owned this `String`. void String_destroy(String*);

14 Using our DIY constructors and destructor const char* c_str = "hello\0world"; String s1, s2, s3, s4; // Initialize s1 to the empty string: String_construct_default(&s1);

14 Using our DIY constructors and destructor const char* c_str = "hello\0world"; String s1, s2, s3, s4; // Initialize s1 to the empty string: String_construct_default(&s1); // Initialize s2 to the string "hello": String_construct_c_str(&s2, c_str);

14 Using our DIY constructors and destructor const char* c_str = "hello\0world"; String s1, s2, s3, s4; // Initialize s1 to the empty string: String_construct_default(&s1); // Initialize s2 to the string "hello": String_construct_c_str(&s2, c_str); // Initialize s3 to the string "hello\0world": String_construct_range(&s3, c_str, c_str + 11)

14 Using our DIY constructors and destructor const char* c_str = "hello\0world"; String s1, s2, s3, s4; // Initialize s1 to the empty string: String_construct_default(&s1); // Initialize s2 to the string "hello": String_construct_c_str(&s2, c_str); // Initialize s3 to the string "hello\0world": String_construct_range(&s3, c_str, c_str + 11) // Initialize s4 to be a copy of s3: String_construct_copy(&s4, &s3);

String_destroy(&s1); String_destroy(&s2); String_destroy(&s3); String_destroy(&s4); 14 Using our DIY constructors and destructor const char* c_str = "hello\0world"; String s1, s2, s3, s4; // Initialize s1 to the empty string: String_construct_default(&s1); // Initialize s2 to the string "hello": String_construct_c_str(&s2, c_str); // Initialize s3 to the string "hello\0world": String_construct_range(&s3, c_str, c_str + 11) // Initialize s4 to be a copy of s3: String_construct_copy(&s4, &s3);

15 DIY constructor implementations (1/5) void String_construct_default(String* this) this->capacity_ = 0; this->size_ = 0; this->data_ = nullptr; }

15 DIY constructor implementations (1/5) // Never do this: #define this actually_not_this void String_construct_default(String* this) this->capacity_ = 0; this->size_ = 0; this->data_ = nullptr; }

16 DIY constructor implementations (2/5) void String_construct_move(String* this, String* other) this->capacity_ = other->capacity_; this->size_ = other->size_; this->data_ = other->data_; } other->capacity_ = 0; other->size_ = 0; other->data_ = nullptr;

17 DIY constructor implementations (3/5) void String_construct_copy(String* this, const String* other) String_construct_range( this, other->data_, other->data_ + other->size_); }

18 DIY constructor implementations (4/5) void String_construct_c_str(String* this, const char* s) String_construct_range(this, s, s + std::strlen(s)); }

DIY constructor implementations (5/5) void String_construct_range(String* this, const char* begin, const char* end) size_t size = end - begin; if (size == 0) String_construct_default(this); return; } } this->capacity_ = size + 1; this->size_ = size; this->data_ = new char[size + 1]; this->data_[size] = '\0'; std::memcpy(this->data_, begin, size); 19

20 Okay, so new and delete The new operator allocates on the free store, and the delete operator deallocates new-allocated objects. (What s the free store? Just like the heap, but a different place.)

20 Okay, so new and delete The new operator allocates on the free store, and the delete operator deallocates new-allocated objects. (What s the free store? Just like the heap, but a different place.) Each comes in two basic forms: allocate deallocate Single object: T* p = new T; delete p; Array: T* p = new T[N]; delete [] p; (UB if your delete form doesn t match the new form.)

21 How does new differ from malloc? It never returns nullptr and always calls constructors: T* operator new() T* result = free_store_malloc(sizeof(t)); if (! result) throw something; T_construct_default(result); return result; }

21 How does new differ from malloc? It never returns nullptr and always calls constructors: T* operator new() T* result = free_store_malloc(sizeof(t)); if (! result) throw something; T_construct_default(result); return result; } For symmetry, delete calls destructors: void operator delete(t* ptr) T_destroy(ptr); free_store_free(ptr); }

T* operator new[](size_t size) layout* result = free_store_malloc(sizeof(layout) + size * sizeof(t)); if (! result) throw something; result->size = size; for (size_t i = 0; i < size; ++i) T_construct_default(result->data + i); return result->data; } 22 How new[] might work struct layout size_t size; T data[0]; };

23 Implementing the destructor void String_destroy(String* this) delete [] this->data_; }

24 DIY Assigners Unlike constructors, assigners require that this already be initialized. // Makes `this` a copy of `other`: void String_assign_copy(String* this, const String* other) // Moves contents of `other` to `this`, // leaving `other` empty: void String_assign_move(String* this, String* other)

25 Implementing the assigners (1/2) void String_assign_move(String* this, String* other) delete [] this->data_; this->capacity_ this->size_ this->data_ = other->capacity_; = other->size_; = other->data_; } other->capacity_ = 0; other->size_ = 0; other->data_ = nullptr;

Implementing the assigners (2/2) void String_assign_copy(String* this, const String* other) // Reallocate only if capacity is insufficient: if (other->size_ > 0 && other->size_ + 1 > this->capacity_) char* new_data = new char[other->size_ + 1]; delete [] this->data_; this->data_ = new_data; this->capacity_ = other->size_ + 1; } if (this->data_ && other->data) std::memcpy(this->data_, other->data_, other->size_ + 1); else if (this->data_) this->data_[0] = '\0'; } this->size_ = other->size_; 26

27 Non-lifecycle operations bool String_empty(const String* this); size_t String_size(const String* this); char String_index(const String* this, size_t index); char* String_index_mut(String* this, size_t index); void String_push_back(String* this, char c); void String_pop_back(String* this);

28 Pushing and popping void String_push_back(String* this, char c) ensure_capacity(this, this->size_ + 2); this->data_[this->size_++] = c; this->data_[this->size_] = '\0'; } void String_pop_back(String* this) this->data_[--this->size_] = '\0'; }

29 An important helper static void ensure_capacity(string* this, size_t min_cap) if (this->capacity_ < min_cap) size_t new_cap = std::max(min_cap, 2 * this->capacity_); char* new_data = new char[new_cap]; if (this->data_) std::memcpy(new_data, this->data_, this->size_ + 1); delete [] this->data_; this->data_ = new_data; this->capacity_ = new_cap; } }

After the exam: Intro to GE211 30