C++ Programming Lecture 4 Software Engineering Group

Similar documents
C++ Programming Lecture 7 Software Engineering Group

C++ Programming Lecture 1 Software Engineering Group

Vector and Free Store (Pointers and Memory Allocation)

C++ Programming Lecture 7 Software Engineering Group

C++ Programming Lecture 6 Software Engineering Group

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

Chapter 17 vector and Free Store

CSE 374 Programming Concepts & Tools. Hal Perkins Spring 2010

C++ Programming Lecture 2 Software Engineering Group

G52CPP C++ Programming Lecture 20

CSE 303: Concepts and Tools for Software Development

Chapter 17 vector and Free Store. Bjarne Stroustrup

Chapter 18 Vectors and Arrays [and more on pointers (nmm) ] Bjarne Stroustrup

Introducing C++ to Java Programmers

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

CSCI-1200 Data Structures Spring 2016 Lecture 6 Pointers & Dynamic Memory

C++ Programming Lecture 13 Software Engineering Group

COMP6771 Advanced C++ Programming

Modern C++ for Computer Vision and Image Processing. Igor Bogoslavskyi

vector and Free Store

Vector and Free Store (Vectors and Arrays)

Principles of Programming Pointers, Dynamic Memory Allocation, Character Arrays, and Buffer Overruns

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

C++ Programming Lecture 8 Software Engineering Group

CA31-1K DIS. Pointers. TA: You Lu

Object-Oriented Programming for Scientific Computing

CS 31: Intro to Systems Pointers and Memory. Kevin Webb Swarthmore College October 2, 2018

CS 31: Intro to Systems Pointers and Memory. Martin Gagne Swarthmore College February 16, 2016

Chapter 17 vector and Free Store

Lecture 14. No in-class files today. Homework 7 (due on Wednesday) and Project 3 (due in 10 days) posted. Questions?

Lecture Topics. Administrivia

Operating Systems CMPSCI 377, Lec 2 Intro to C/C++ Prashant Shenoy University of Massachusetts Amherst

Midterm Review. PIC 10B Spring 2018

Ch. 12: Operator Overloading

04-17 Discussion Notes

Lecture Notes on Memory Layout

CS201- Introduction to Programming Current Quizzes

CSci 4061 Introduction to Operating Systems. Programs in C/Unix

05-01 Discussion Notes

Launchpad Lecture -10

Dynamic Allocation in C

C11: Garbage Collection and Constructors

Pointers and Arrays CS 201. This slide set covers pointers and arrays in C++. You should read Chapter 8 from your Deitel & Deitel book.

And Even More and More C++ Fundamentals of Computer Science

CMSC 202 Section 010x Spring Justin Martineau, Tuesday 11:30am

Object Reference and Memory Allocation. Questions:

Outline. 1 Function calls and parameter passing. 2 Pointers, arrays, and references. 5 Declarations, scope, and lifetimes 6 I/O

A brief introduction to C++

Introduction to C++ Professor Hugh C. Lauer CS-2303, System Programming Concepts

6. Pointers, Structs, and Arrays. March 14 & 15, 2011

ALL ABOUT POINTERS C/C++ POINTERS

Short Notes of CS201

Pointers, Dynamic Data, and Reference Types

What goes inside when you declare a variable?

Outline. A C++ Linked Structure Class A C++ Linked List C++ Linked Dynamic Memory Errors In-class work. 1 Chapter 11: C++ Linked Structures

6. Pointers, Structs, and Arrays. 1. Juli 2011

Dynamic Allocation in C

Vectors of Pointers to Objects. Vectors of Objects. Vectors of unique ptrs C++11. Arrays of Objects

CS162 - POINTERS. Lecture: Pointers and Dynamic Memory

CS201 - Introduction to Programming Glossary By

04-19 Discussion Notes

PIC 10A Objects/Classes

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

Fast Introduction to Object Oriented Programming and C++

C++ Mini-Course. Part 1: Mechanics Part 2: Basics Part 3: References Part 4: Const Part 5: Inheritance Part 6: Libraries Part 7: Conclusion. C Rulez!

C++ Programming Lecture 5 Software Engineering Group

377 Student Guide to C++

Outline. User-dened types Categories. Constructors. Constructors. 4. Classes. Concrete classes. Default constructor. Default constructor

C10: Garbage Collection and Constructors

G52CPP C++ Programming Lecture 13

MARKING KEY The University of British Columbia MARKING KEY Computer Science 260 Midterm #1 Examination 12:30 noon, Tuesday, February 14, 2012

MARKING KEY The University of British Columbia MARKING KEY Computer Science 260 Midterm #2 Examination 12:30 noon, Thursday, March 15, 2012

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

CS 251 INTERMEDIATE SOFTWARE DESIGN SPRING C ++ Basics Review part 2 Auto pointer, templates, STL algorithms

1/29/2011 AUTO POINTER (AUTO_PTR) INTERMEDIATE SOFTWARE DESIGN SPRING delete ptr might not happen memory leak!

Abstract. Vector. Overview. Building from the ground up. Building from the ground up 1/8/10. Chapter 17 vector and Free Store

THE GOOD, BAD AND UGLY ABOUT POINTERS. Problem Solving with Computers-I

Lecture 2, September 4

Advanced Programming & C++ Language

CS3157: Advanced Programming. Outline

Quiz Start Time: 09:34 PM Time Left 82 sec(s)

CS201 Some Important Definitions

2 ADT Programming User-defined abstract data types

Pointers and Memory 1

CS201 Latest Solved MCQs

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

Variables, Memory and Pointers

Pointers. Developed By Ms. K.M.Sanghavi

CPSC 427: Object-Oriented Programming


the gamedesigninitiative at cornell university Lecture 7 C++ Overview

Run Time Environment

Dynamic Memory Allocation

More Advanced Class Concepts

Pointer Basics. Lecture 13 COP 3014 Spring March 28, 2018

Pointers and References

Pointers. 1 Background. 1.1 Variables and Memory. 1.2 Motivating Pointers Massachusetts Institute of Technology

Operator overloading

Object-Oriented Principles and Practice / C++

INITIALISING POINTER VARIABLES; DYNAMIC VARIABLES; OPERATIONS ON POINTERS

Transcription:

C++ Programming Lecture 4 Software Engineering Group Philipp D. Schubert

VKrit Date: 24.11.2017 Time: 15:45 h Your opinion is important! Please use the free text comments

Contents 1. Operator overloading 2. Memory 3. Dynamic memory allocation 4. Copy constructor/ assign (a real example) 5. Move constructor/ assign (a real example) 6. Notes on dynamic memory allocation

Operators Operators are e.g. = operator= + operator+ - operator- * operator* / operator/ == operator== [] operator[] < operator< > operator> <= operator<= And lots of others

Operator overloading Operators have a meaning int sum = 4 + 5; + is the mathematical plus that sums up numbers But operators can be overloaded An overloaded operator has more than one meaning Meaning depends on context Overloading operators is a powerful instrument It allows you to write code & implement algorithms exactly like shown in maths text books Have you ever used an overloaded operator? Yes! Remember strings

Operator overloading Rather natural use of + In context of strings string a = "AAAA"; string b = "BBB"; string result = a + b; Overloaded operators should be designed naturally Should work as you would expect! Please don t overload string a = "AAAA"; string b = "BBB"; string result = a + b; to delete the content of a and b and fill result with "It s just a prank!"

Operator overloading What operators can be overloaded? Please refer to http://en.cppreference.com/w/cpp/language/operators If you write a data type only overload operators that are useful whose meaning is clear Do not overload all operators or as much as possible Bjarne Stoustrup and the idea of custom operators! E.g. operator** Pythons power operator Arbitrary defined operators would be possible But not intuitive

Simple example: operator<< Definition inside #include <iostream> using namespace std; struct Type { Type(int i, double d) : i(i), d(d) { int i; double d; friend ostream& operator<< (ostream& os, const Type &t) { return os << t.i << " and " << t.d; ; int main() { Type t(1, 2.222); cout << t << '\n'; return 0; Definition outsite #include <iostream> using namespace std; struct Type { Type(int i, double d) : i(i), d(d) { int i; double d; ; ostream& operator<< (ostream& os, const Type &t) { return os << t.i << " and " << t.d; int main() { Type t(1, 2.222); cout << t << '\n'; return 0;

Operator overloading Remember our Vec3 type class Vec3 { private: double x; double y; double z; public: Vec3() : x(0), y(0), z(0) { Vec3(double x, double y, double z) : x(x), y(y), z(z) { constexpr size_t size() { return 3; double euclidean_length() { return sqrt(x*x+y*y+z*z); friend ostream& operator<< (ostream& os, const Vec3& v){ return os << v.x << "\n" << v.y << "\n" << v.z; ; Why is operator<< declared as friend? Obviously it is not a member function It receives a Vec3 as a parameter If a function is declared as friend it can access the type s private variables! Vec3 v1(4,5,6); cout << v1 << \n ;

Operator overloading Let s overload operator+ and operator[] for convenience class Vec3 { private: double x; double y; double z; public: Vec3() : x(0), y(0), z(0) { Vec3(double x, double y, double z) : x(x), y(y), z(z) { constexpr size_t size() { return 3; double euclidean_length() { return sqrt(x*x+y*y+z*z); double& operator[] (size_t idx) { switch (idx) { case 0: return x; break; case 1: return y; break; case 2: return z; break; We need a const version of operator[] Vec3 v; v[1] = 12; const Vec3 v; v[1] = 14; // does not work! const double& operator[] (size_t idx) const { switch (idx) { case 0: return x; break; case 1: return y; break; case 2: return z; break; friend Vec3 operator+ (Vec3 lhs, const Vec3& rhs) { for (size_t i = 0; i < lhs.size(); ++i) lhs[i] += rhs[i]; return lhs; friend ostream& operator<< (ostream& os, const Vec3& v) { return os << v.x << " " << v.y << " " << v.z; ; A const function or operator is one, that does not modify the data members!

Operator overloading Now we can use int main() { Vec3 v1(1,2,3); Vec3 v2(4,5,6); Vec3 v3 = v1 + v2; cout << v3 << \n ; return 0; Output 5 7 9 Great it works!

Operator overloading Caution: why is it not a smart idea to check two double numbers for equality? class Vec3 { private: double x; double y; double z; public: Vec3() : x(0), y(0), z(0) { Vec3(double x, double y, double z); constexpr size_t size(); double euclidean_length(); double& operator[] (size_t idx); const double& operator[] (size_t idx) const; friend Vec3 operator+ (Vec3 lhs, const Vec3& rhs); friend ostream& operator<< (ostream& os, const Vec3& v); ; You are now able to write these yourself friend Vec3 operator- (Vec3 lhs, const Vec3& rhs); friend double operator* (const Vec3& lhs, const Vec3& rhs); friend Vec3 operator* (Vec3 lhs, double rhs); friend Vec3 operator% (Vec3 lhs, const Vec3& rhs); // caution, may not be intuitive in this example! friend bool operator< (const Vec3& lhs, const Vec3& rhs); friend bool operator> (const Vec3& lhs, const Vec3& rhs); friend bool operator<=(const Vec3& lhs, const Vec3& rhs); friend bool operator>=(const Vec3& lhs, const Vec3& rhs); friend bool operator==(const Vec3& lhs, const Vec3& rhs); friend bool operator!=(const Vec3& lhs, const Vec3& rhs); Only have to implement operator< and operator== for comparison Why? Others can be expressed in < and ==

Custom operators Not possible in the language But It is possible using some ugly hack Later on we will do a fun lecture I will show some of these things

Memory layout Memory layout in Linux systems (and C/C++ programs) High addresses Kernel Containing command-line & environment variables (OS data) Stack Contains function parameters & functions return address Local variables Heap Allows allocation of huge chunks of memory Data Contains initialized and uninitialized (global) variables Text RO contains program text (machine instructions) Memory is just a linear piece of addressable locations Low addresses Kernel Stack Heap Data Text

Memory layout Kernel Stack Please consider this website http://www.geeksforgeeks.org/memory-layout-of-c-program/ This page explains in detail why we have such a memory layout I highly encourage you to read this page Heap Data Text

Why dynamic memory allocation? Consider static memory int buffer[10]; Problem How to store more than 10 elements? What it I do not know the number of elements up-front? How do I store a million elements? Stack data is usually limited by the operating system What if data should be used in more than one scope? Dynamically allocated heap data solves the problem Simply take (allocate) what you need! Allocate memory chunks as big as you like (size of RAM chips)! Kernel Stack Heap Data Text

Dynamic memory allocation Ability to allocate what your RAM chips provide Simply allocate what you need! But caution You have to do the clean-up yourself No garbage collector (like in Java)! Free the memory after usage The memory is yours until you free it: There is no out of scope! Do not lose the memory handle!!! The keyword for allocation is new The keyword for deallocation is delete

Dynamic memory allocation Remember pointers int i = 42; int *i_ptr = &i; // integer variable i // pointer i_ptr points to i Pointers will now become really useful They are inevitable even Operator new allocates the amount of memory you need But new cannot provide a name for allocated memory! Thus it simply returns a pointer to your memory Caution Do not lose size information! Otherwise you risk undefined reads & writes! Do not forget to delete it or do not delete twice! Otherwise you leak memory or result in undefined behavior! [Picture from images.google.de]

About Undefined Behavior Caution this talk may leads to nightmares Undefined Behavior is awesome!, Piotr Padlewski https://www.youtube.com/watch?v=ehyhyaia5so

Allocate and delete memory The keyword for allocation is new In fact it is an operator (that can even be overloaded) Standard signatures are void* operator new ( std::size_t count ); // for objects void* operator new[]( std::size_t count ); // for arrays Notice new is returning a void pointer If memory cannot be allocated new throws an std::bad_alloc exception (next lecture) The keyword for deallocation is delete In fact it is a operator (that can even be overloaded) Standard signatures are void operator delete ( void* ptr ); // for objects void operator delete[]( void* ptr ); // for arrays Every new needs a delete otherwise your program contains an leak/ error

Allocate and delete memory void* operator new ( std::size_t count ); void* operator new[]( std::size_t count ); void operator delete ( void* ptr ); void operator delete[]( void* ptr ); // for objects // for arrays // for objects // for arrays Why is there a difference between objects and arrays? Just an syntactic oddity Has no use at all Even worse Do not confuse between them: Do not allocate with new and free with delete[] (and vice versa)

Double deletion Task allocate one single int int main() { int *dyn_int = new int; *dyn_int = 42; cout << *dyn_int << \n ; // we have a leak here // how to fix? delete dyn_int; dyn_int = nullptr; delete dyn_int; return 0;

Valgrind, a tool to detect memory misuse Valgrind was developed by Julian Seward British compiler construction specialist Valgrind is a tool-suite that allows detection of memory errors It runs the program under analysis multiple times It stops program many times during its execution In these breaks it analyzes registers, stack, and collects all these information With help of these information it can determine weather a program has some memory issues Caution: the program to analyze is executed ~100 times slower than usually Analyzing big projects needs time It is worth while There are not many ways of detection if a program has memory issues Double delete program crashes Missing delete program leaks consumes more & more memory, until crash

Valgrind, a tool to detect leaks int main() { int *dyn_int = new int; *dyn_int = 42; cout << *dyn_int << \n ; // we have a leak here return 0;

Valgrind, a tool to detect leaks int main() { int *dyn_int = new int; *dyn_int = 42; cout << *dyn_int << \n ; delete dyn_int; dyn_int = nullptr; return 0;

Allocate arrays int main() { int *array = new int[10]; for (int i = 0; i < 10; ++i) { array[i] = 13; // this is pointer arithmetic, same meaning as array[i] *(array+i) += 2; // do useful things with array delete[] array; // we have to use the array delete return 0; array Kernel Stack int,int,int,int,int,int,int,int,int, int Heap Problem with dynamic arrays The programmer has store size information himself Otherwise possibility for index out of bounds Undefined behavior or segmentation fault Data Text

Allocate 2D arrays int main() { int rows = 3; int cols = 4; int **matrix = new int*[rows]; for (int row = 0; row < rows; ++row) matrix[row] = new int[cols]; for (int row = 0; row < rows; ++row) for (int column = 0; column < cols; ++column) matrix[row][column] = 42; // do useful stuff with matrix **matrix Kernel Stack *int,*int,*int int,int,int,int Heap int,int,int,int for (int row = 0; row < rows; ++row) delete[] matrix[row]; delete[] matrix; return 0; Data Text int,int,int,int

Allocate a user-defined type/ object struct Vertex { Vertex() : x(0), y(0), z(0) { Vertex(double x, double y, double z) : x(x), y(y), z(z) { double x, y, z; friend ostream& operator<< (ostream& os, const Vertex& v) { return os << v.x << " " << v.y << " " << v.z; ; int main() { Vertex *v1 = new Vertex; Vertex *v2 = new Vertex(1, 2, 3); Vertex v3(3, 2, 1); // -> is shorthand to (*v2).x (dereference & access content) v2->x = 42; cout << *v2 << \n ; delete v1; v1 = nullptr; delete v2; v2 = nullptr; return 0; *v1*v2 Kernel double,double,double Stack double,double,double Heap double,double,double Data Text

Copy & move using dynamic memory [Figure from https://karstenkares.files.wordpress.com/2016/01/hdwallpapersimage-com-middle-earth-shadow-of-mordor-wide-hd-wallpaper-1920x1080.jpg]

Copy constructor & copy assign gone wrong #include <iostream> using namespace std; struct DynInt { DynInt(int i) : i_ptr(new int(i)) { ~DynInt() { delete i_ptr; // we have to clean up DynInt(const DynInt &di) = default; DynInt& operator= (const DynInt &di) = default; friend ostream& operator<< (ostream& os, const DynInt &di) { return os << *di.i_ptr; int *i_ptr; ; int main() { DynInt di1(42); DynInt di2 = v1; // call copy assignment operator *di2.i_ptr = 100; // ups! we copy the pointer i_ptr, but not what it points-to! cout << di1 << '\n'; cout << di2 << '\n'; return 0; // even more ups, we call dtor for di1 and di2 we call dtor twice for the same heap object

Copy constructor & copy assign: How to fix it #include <iostream> using namespace std; struct DynInt { DynInt(int i) : i_ptr(new int(i)) { ~DynInt() { delete i_ptr; // we have to clean up ; DynInt(const DynInt &di) : i_ptr(new int(*(di.i_ptr))) {; // create a real copy! DynInt& operator= (const DynInt &di) = default; // this now works, since it calls copy constructor friend ostream& operator<< (ostream& os, const DynInt &di) { return os << *di.i_ptr; int *i_ptr; int main() { DynInt di1(42); DynInt di2 = v1; *di2.i_ptr = 100; cout << di1 << '\n'; cout << di2 << '\n'; return 0; // call copy assignment operator // does this work? // does this work?

Move constructor & move assign gone wrong #include <iostream> using namespace std; struct DynInt { DynInt(int i) : i_ptr(new int(i)) { ~DynInt() { delete i_ptr; // we have to clean up ; DynInt(const DynInt &di) : i_ptr(new int(*(di.i_ptr))) {; // create a real copy! DynInt& operator= (const DynVecUser& dvu) = default; // this now works, since it calls copy constructor DynInt(DynInt &&di) = default; DynInt& operator= (DynInt &&di) = default; friend ostream& operator<< (ostream& os, const DynInt &di) { return os << *di.i_ptr; int *i_ptr; int main() { DynInt di1(42); DynInt di2 = move(di1); *di2.i_ptr = 100; cout << di2 << '\n'; return 0; // call move assignment operator use: #include <utility> // does this work? // does this work?

Move constructor & move assign: How to fix it #include <iostream> using namespace std; struct DynInt { DynInt(int i) : i_ptr(new int(i)) { ~DynInt() { delete i_ptr; // we have to clean up ; DynInt(const DynInt &di) : i_ptr(new int(*(di.i_ptr))) {; // create a real copy! DynInt& operator= (const DynVecUser& dvu) = default; // this now works, since it calls copy constructor DynInt(DynInt &&di) { i_ptr = di.i_ptr; di.i_ptr = nullptr; // steal the data, and set old pointer to null! DynInt& operator= (DynInt &&di) = default; // this now works, since it calls move constructor friend ostream& operator<< (ostream& os, const DynInt &di) { return os << *di.i_ptr; int *i_ptr; int main() { DynInt di1(42); DynInt di2 = move(di1); *di2.i_ptr = 100; cout << di2 << '\n'; return 0; // call move assignment operator use: #include <utility> // does this work? // does this work?

Relax now We now know how to handle special member functions in context of dynamic memory allocation! It will not get anymore complicated than that! [Picture from https://bplusmovieblog.files.wordpress.com/2014/10/the-matrix-2825.png?w=590]

A note on special member functions using STL types STL types provide many useful constructors STL types know how they have to be destructed copied copied assigned moved move assigned If your are dealing with types having only primitive (build-in) and STL data members = default works fine If you are dealing with dynamic memory yourself, you now know how to deal with special member functions

A note on dynamic memory allocation Raw new and delete should rarely be used anymore Too error prone Usually no need for raw new and delete There are exceptions of course If you need to allocate one object Just do so using stack memory and return by value (RVO and move() take care of performance) move() the variable between scopes, if you want them to live longer then one scope If object is too big for stack, then use dynamic memory allocation #include <iostream> #include <utility> using namespace std; int main() { int outer_scope; { int inner_scope = 42; outer_scope = move(inner_scope); cout << outer_scope << '\n'; return 0;

A note on dynamic memory allocation If you need a dynamically array of objects Use vector It was created for this purpose Acts as a safe wrapper Carries size information

A note on dynamic memory allocation If you need raw new and delete nevertheless Use smart pointers rather than raw pointers Using smart pointer you do not need to call delete Smart pointers do the clean-up themselves You cannot leak anymore! The poor man s garbage collector We will see them in the next lecture

Recap Operator overloading Memory layout in operating systems Dynamic memory allocation Dynamic memory allocation for arrays Dynamic memory allocation for objects Valgrind Copy constructor Move constructor Notes on dynamic memory allocation

Thank you for your attention Questions?