Lecture 5 Operator Overloading Introduction to STL

Similar documents
use static size for this buffer

COMP6771 Advanced C++ Programming

COMP6771 Advanced C++ Programming

CE221 Programming in C++ Part 1 Introduction

#include <iostream> #include <cstdlib>

COEN244: Class & function templates

by Pearson Education, Inc. All Rights Reserved. 2

Chapter 17: Linked Lists

PIC10B/1 Winter 2014 Final Exam Study Guide

Chapter 17: Linked Lists

Introduction to C++ Systems Programming

PIC10B/1 Winter 2014 Exam I Study Guide

What will happen if we try to compile, link and run this program? Do you have any comments to the code?

Purpose of Review. Review some basic C++ Familiarize us with Weiss s style Introduce specific constructs useful for implementing data structures

CS242 COMPUTER PROGRAMMING

Function Templates. Consider the following function:

PHY4321 Summary Notes

Operator overloading

CS197c: Programming in C++

Short Notes of CS201

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

IV. Stacks. A. Introduction 1. Consider the 4 problems on pp (1) Model the discard pile in a card game. (2) Model a railroad switching yard

CS201 - Introduction to Programming Glossary By

Cours de C++ Introduction

C++ Programming Fundamentals

Lesson 13 - Vectors Dynamic Data Storage

Templates (again) Professor Hugh C. Lauer CS-2303, System Programming Concepts

List, Stack, and Queues

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

Sequential Containers. Ali Malik

Part XI. Algorithms and Templates. Philip Blakely (LSC) C++ Introduction 314 / 370

7 TEMPLATES AND STL. 7.1 Function Templates

Chapter 15 - C++ As A "Better C"

C++ Programming Fundamentals

Introduction to Programming Using Java (98-388)

(8 1) Container Classes & Class Templates D & D Chapter 18. Instructor - Andrew S. O Fallon CptS 122 (October 8, 2018) Washington State University

CSI33 Data Structures

C++ 11 and the Standard Library: Containers, Iterators, Algorithms

EL2310 Scientific Programming

Chapter 18 - C++ Operator Overloading

STL Quick Reference for CS 241

Absolute C++ Walter Savitch

THINK LIKE CREATIVE PROBLEM SOLVING V. ANTON SPRAUL

The Standard Template Library. An introduction

CMSC 341 Lecture 6 Templates, Stacks & Queues. Based on slides by Shawn Lupoli & Katherine Gibson at UMBC

Operator Overloading in C++ Systems Programming

Tuesday, 22 September 2009

C++ TEMPLATES. Templates are the foundation of generic programming, which involves writing code in a way that is independent of any particular type.

Lecture-5. STL Containers & Iterators

Modern and Lucid C++ for Professional Programmers. Part 7 Standard Containers & Iterators. Department I - C Plus Plus

C++ (Non for C Programmer) (BT307) 40 Hours

Templates Templates are functions or classes that are parameterized. We have already seen a few in STL:

18. Dynamic Data Structures I. Dynamic Memory, Addresses and Pointers, Const-Pointer Arrays, Array-based Vectors

Week 8: Operator overloading

CSE 12 Week Eight, Lecture One

Preface... (vii) CHAPTER 1 INTRODUCTION TO COMPUTERS

Chapter 18: Stacks And Queues

Data Structures and Algorithms

STL: C++ Standard Library

1. The term STL stands for?

CS304 Object Oriented Programming Final Term

Object-Oriented Design (OOD) and C++

Programming with Haiku

Abstract Data Types 1

Templates and Vectors

C++ Exception Handling 1

Chapter 18: Stacks And Queues. Pearson Education, Inc. Publishing as Pearson Addison-Wesley

CSCI-1200 Data Structures Fall 2018 Lecture 22 Hash Tables, part 2 & Priority Queues, part 1

Stacks and their Applications

Interview Questions of C++

Type Aliases. Examples: using newtype = existingtype; // C++11 typedef existingtype newtype; // equivalent, still works

Computer Science II Lecture 2 Strings, Vectors and Recursion

EE 355 Unit 10. C++ STL - Vectors and Deques. Mark Redekopp

Abstract Data Types. CptS 223 Advanced Data Structures. Larry Holder School of Electrical Engineering and Computer Science Washington State University

Object-Oriented Programming

About this exam review

Dynamic Data Structures

CS

B16 Object Oriented Programming

EECE.3220: Data Structures Spring 2017

TDDD38 - Advanced programming in C++

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

Abstraction and Encapsulation. Benefits of Abstraction & Encapsulation. Concrete Types. Using Typedefs to streamline classes.

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

Programming, numerics and optimization

Praktikum: Entwicklung interaktiver eingebetteter Systeme

Advanced C ++ Philip Blakely. Laboratory for Scientific Computing, University of Cambridge. Philip Blakely (LSC) Advanced C++ 1 / 119

COMP6771 Advanced C++ Programming

Polymorphism. Programming in C++ A problem of reuse. Swapping arguments. Session 4 - Genericity, Containers. Code that works for many types.

Unit 4 Basic Collections

Object-Oriented Programming for Scientific Computing

Abstract Data Types 1

Introducing C++ to Java Programmers

CSCE 110 PROGRAMMING FUNDAMENTALS

Simulations. buffer of fixed capacity using the STL deque. modeling arrival times generating and processing jobs

COMP6771 Advanced C++ Programming

Cpt S 122 Data Structures. Templates

Chapter 5. The Standard Template Library.

AN OVERVIEW OF C++ 1

Outline. Variables Automatic type inference. Generic programming. Generic programming. Templates Template compilation

Transcription:

Lecture 5 Operator Overloading Introduction to STL

Operator Overloading Operator Overloading means making the compiler's built in operator symbols work with classes Operator symbols are things like + - = * etc To do this with classes we may want to use a syntax as follows 1 #include "Vector.h" 2 3 Vector p1(0,0,0,1) 4 Vector p2(2,3,2,1) 5 6 Vector p3=p1+p2;

So how do we do this? To allow a similar operation as shown previously we have to code the mechanism ourselves In effect the + and = operator must be overloaded to be methods of the class By overloading operators in this way we can give the classes in a system a common interface, allowing us to perform similar operations on a range of different objects.

Overloading and the assignment operator The = operator is already overloaded to work with objects as well as simple data types This has already been see with the copy constructor class_name object2 = object1; This means that object2 is instantiated with the same state as object1, We can also do this in normal code for example object2=object1; This behaviour is default for the = operator however we can program our own overloaded = operator within the class. This is required when pointers are used as the object will point only to the memory address and if the initial object is destroyed so will the memory address where the pointer points to, Therefore code will be required to create and copy the pointer data

C++ Syntax The syntax required for operator overloading is : The operator keyword And one of the 40 operator which may be overloaded as shown below 1 new delete + - * / % += -= *= /= %= ++ -- = 2 3 ˆ & ˆ= &= = << >> >>= <<= 4 5 < > ==!= <= >= 6 7! && 8 9 ->* -> 10 11, comma operator 12 13 () function call operator 14 15 [] subscripting operator

Syntax for Operator Overloading if( object1 > object2 ) returns true(1) or false (0) Object using operator parameter objects The syntax for operator overloading is as follows return_type operator symbol(parameter list...) The return type for a relational operator is a Boolean value

Arithmetic Operator Overloading A temporary object is returned from the operator method = + object object object object to receive result object using operator parameter operator Arithmetic operators return an object of the appropriate class as shown

The parameter List The parameter list usually consists of an object of the class This is passed by reference rather than by value to avoid making a copy of the object Therefore the const prefix is used to stop the reference object being modified in the class 1 //less than (relational) 2 3 bool operator <(const Object &object); 4 5 //minus (arithmetic) 6 7 Object operator -(const Object &object);

Overloading relational operators Vector.h 1 /// @brief check for equality uses FCompare 2 /// @param[in] _v the vector to check against 3 /// @returns true or false 4 bool operator==( 5 const Vector &_v 6 )const; 7 /// @brief not equal check 8 /// @param[in] _v the vector to check against 9 /// @returns true of false 10 bool operator!=( 11 const Vector &_v 12 )const;

Overloading relational operators Vector.cpp 1 bool Vector::operator==( 2 const Vector& _v 3 )const 4 { 5 return ( 6 FCompare(_v.m_x,m_x) && 7 FCompare(_v.m_y,m_y) && 8 FCompare(_v.m_z,m_z) 9 ); 10 } 11 12 bool Vector::operator!=( 13 const Vector& _v 14 )const 15 { 16 return ( 17!FCompare(_v.m_x,m_x) 18!FCompare(_v.m_y,m_y) 19!FCompare(_v.m_z,m_z) 20 ); 21 } Vector.h 1 #ifndef EPSILON 2 const float EPSILON = 0.001f; 3 #endif 4 #define FCompare(a,b) \ 5 ( ((a)-epsilon)<(b) && ((a)+epsilon)>(b) )

Overloading the arithmetic operator 1 2 3 4 Vector.h 1 Vector v1(1,2,3) 2 Vector v2(2,3,4) 3 4 Vector v3=v1+v2 5 /// @brief + operator add vector+vector 6 /// @param[in] &_v the value to add 7 /// @returns the vector + v 8 Vector operator+( 9 const Vector &_v 10 )const; 11 12 Vector.cpp 13 14 15 16 Vector Vector::operator+( 17 const Vector& _v 18 )const 19 { 20 return Vector( 21 m_x+_v.m_x, 22 m_y+_v.m_y, 23 m_z+_v.m_z, 24 m_w 25 ); 26 }

friend functions A friend function is used to allow access to private or protected data in a class from outside the class. Normally a function which is not a member of a class cannot access the private attributes In the previous case we need to access the private stream to insert or extract to so we make the member for << and >> a friend to the stream so we can access the data. It is best to limit the use of friend functions / classes however as we will see in the NGL library it is quite useful to make some classes friends with each other

Overloading Insertion and Extraction 1 #include "Vector.h" 2 #include <iostream> 3 #include <cstdlib> 4 5 int main() 6 { 7 std::cout<<"vector Test\n"; 8 Vector v1(1,2,3); 9 Vector v2(2,3,4); 10 Vector *v3=new Vector(2,3,4); 11 12 std::cout<<v1<<v2<<v3<<"\n"; 13 14 15 std::cout<<v1<<v2<<"\n"; 16 std::cout<<v2+v3<<"\n"; 17 return EXIT_SUCCESS; 18 19 } Vector.h 1 2 3 4 5 friend std::ostream& operator<<(std::ostream& _output, const Vector& _s); 6 friend std::istream& operator>>(std::istream& _input, Vector &_s); 7 8 friend std::ostream& operator<<(std::ostream& _output, const Vector* _s); 9 friend std::istream& operator>>(std::istream& _input, Vector* _s); 10 11 12 13 14 15 std::ostream& operator<<( 16 std::ostream& _output, 17 const Vector& _v 18 ) 19 { 20 return _output<<"["<<_v.m_x<<","<<_v.m_y<<","<<_v.m_z<<","<<_v.m_w<<"]"; 21 } 22 23 std::istream& operator>>( 24 std::istream& _input, 25 Vector& _s 26 ) 27 { 28 return _input >> _s.m_x >> _s.m_y >> _s.m_z;//>>s.m_w; 29 } 30 31 std::ostream& operator<<( 32 std::ostream& _output, 33 const Vector* _s 34 ) 35 { 36 return _output<<"["<<_s->m_x<<","<<_s->m_y<<","<<_s->m_z<<","<<_s->m_w<<"]"; 37 } 38 39 std::istream& operator>>( 40 std::istream& _input, 41 Vector *_s 42 ) 43 { 44 return _input >> _s->m_x >> _s->m_y >> _s->m_z;//>>s->m_w; 45 } Vector.cpp

overloading += 1 2 3 4 5 /// @brief += operator add vector v to current vector 6 /// @param[in] &_v vector to add 7 void operator+=( 8 const Vector& _v 9 ); 10 11 12 13 14 15 void Vector::operator+=( 16 const Vector& _v 17 ) 18 { 19 m_x+=_v.m_x; 20 m_y+=_v.m_y; 21 m_z+=_v.m_z; 22 m_w=0.0; 23 } Vector.h Vector.cpp

overloading [] 1 v2[0]=10; 2 std::cout<<v2[0]<<"\n"; 1 2 3 4 Vector.h 5 /// @brief [] index operator to access the index component of the vector 6 /// @returns this[x] as a float 7 float& operator[]( 8 const int& _i 9 ) ; 10 11 Vector.cpp 12 13 14 15 float& Vector::operator[]( 16 const int& _i 17 ) 18 { 19 assert(_i >=0 _i<=4); 20 return (&m_x)[_i]; 21 }

overloading -() 1 2 3 4 5 Vector operator-() const; 6 7 8 Vector.h Vector.cpp 9 Vector Vector::operator-() const 10 { 11 return Vector(-m_x,-m_y,-m_z,m_w); 12 }

float * Vector As the left side operator is outside the class we declare the float * vector operator in the.h file but outside of the class scope 1 inline Vector operator *(float _k, const Vector &_v) 2 { 3 return Vector(_k*_v.m_x, _k*_v.m_y, _k*_v.m_z,_v.m_w); 4 }

Generic Programming Generic programming allows us to generate an algorithm where the data types used for the algorithm are not defined at the time the user implements the algorithm. Instead we declare a template argument which the compiler will attempt to generate when the user applies the function in a particular context. This is a type of polymorphism more specifically for C++ compile time polymorphism

Polymorphism by Parameter Parametric Overloading allows us to have multiple methods of the same name with different parameters We have already seen this with the constructor method in classes For example we can have the following methods 1 afunction(int value1); 2 afunction(int value1, int value2); 3 afunction(float value1); Note that the return type of a function can not be overloaded and must remain the same value for every method

Parametric Polymorphism (genericity) The primary application of parametric polymorphism is in O-O systems to allow methods to work in a generic way. However these functions are not truly generic as ad-hoc polymorphism is used and each different parameter list has it's own implementation In contrast a generic method will execute the same implementation but be able to accept a range of types as parameters same function name different parameter lists: function(...) (int) (char) (char *) (float) (double) same implimentation for each parameter type

Generic Functions (using templates) In C++ genericity is is achieved by the use of templates We have already used a lot of these when using boost A template will operate on any data type for which the internal implementation is appropriate. For example a template function which compares two objects using the '>' operator to return the greater will operate on any data type (including Objects) where the '>' function is appropriate. From the operator overloading examples last week we can see that we can now also use a simple template function with objects.

But why use templates? We often need to perform a similar process on different data types The data type(s) being processed are passed to a method as parameters With parametric overloading, each type of parameter will cause the compiler to use a different (type specific) method. With genericity, a single generic function is able to process all data types, including those defined by the programmer (i.e. objects) - all data types are handled by one (type generic) model. Genericity allows us to create generic classes, as well as simply using generic functions as methods

Generic Functions Genericity is a more powerful tool than parametric overloading for O-O systems because it does not have to anticipate the type of data parameters which may be supplied at run time. This means it is able to handle dynamic objects of disparate types However, this approach only works if we are able to process all data types in a particular way, this means that we need to have a common interface for all objects used as parameters.

Generic function parameters ISEQUAL(parameter1, parameter2) ISEQUAL? parameter1 == parameter2 With generic functions parameters can be of any type TRUE / FALSE However they must be able to be processed by the function, which in this case means that able to use the '==' operator This will also be true of any objects which use this function as they will need an overloaded '==' operator.

Template Functions Templates are a very powerful tool which will be investigated in more detail when we do container classes Template functions are a generic functions which can have parameters of any data type The C++ syntax for creating a template function is as follows : 1 template <class T> [return type] function(params)

Template Functions template is a C++ keyword, and the name of the generic class name must be enclosed in pointed brackets <...> The class type name can be anything but most examples use T This value T acts as an alias for any data type actually passed to the function (whether that data type is int, char,vector, Matrix, Vector, Colour, banana etc)

Example Linear Interpolation We can use linear interpolation to blend between two values using a real scalar value which ranges from 0-1 The basic formula given two values a and b and the real scalar t we get This can be written in code as p = a +(b a) t; 1 float Lerp(float a, float b, float t) 2 { 3 assert(t>=0 && t<=1); 4 return a+(b-a)*t; 5 }

Problems with polymorphic approach The problem with the previous example is we would need to write a Lerp function for every data type. For Example to interpolate two Vectors we would need 1 float Lerp( 2 Vector _a, 3 Vector _b, 4 float _t 5 ) 6 { 7 Vector r; 8 assert(t>=0 && t<=1.0); 9 p.m_x=_a.m_x+(_b.m_x-_a.m_x)*t; 10 p.m_y=_a.m_y+(_b.m_y-_a.m_y)*t; 11 p.m_z=_a.m_z+(_b.m_z-_a.m_z)*t; 12 13 return r; 14 15 }

A Template Version 1 template <class T> T Lerp( 2 T _a, 3 T _b, 4 ngl::real _t 5 ) 6 { 7 T p; 8 p=_a+(_b-_a)*_t; 9 return p; 10 } 1 Vector v1(1,2,3); 2 Vector v2(2,3,4); 3 4 Vector v3=lerp(v1,v2,0.2); 1 Colour c1(1,0,0,1); 2 Colour c2(0,0.5,1,1); 3 4 Colour mix=lerp(c1,c2,0.2); For this function to work the Objects used must have = + - *(scalar) implemented as operators. 1 float a=2; 2 float b=3; 3 4 float c=lerp(a,b,0.2);

What happens when templates are used As template functions are "generic" functions we do not know what data types are to be used until compile time This means that the compiler has to expand the template function for every data type to be used and create separate type specific functions for each use. For the previous example the compiler would generate 3 different functions one for Point3 one for Colour and one for float data types This means that at compile time if templates are used compilation will be slower as the compiler has to expand the templates into real functions As there is no checking until compilation time for template we do not know whether they will work until the compiler has expanded them. This can lead to error especially when we are using classes as parameters to templates

Template advantages / disadvantages Defining generic classes that are parameterised with types i.e. classes can have types as arguments. A template parameter representing a type variable is denoted as class identifier Template arguments are type names that match type variable parameters A powerful way of defining families of similar classes. Pre-processing of templates expands into a full class specification for every different combination of template arguments. This increases the source code size as well as compilation time.

The Standard Template Library The standard Template Library (STL) takes the idea of Template functions and extends them to a number of typical programming problems. The STL contains templated classes which allow us to generate :- Containers (Ways of containing data) Associative Arrays (Contain data and key pairs) Iterators (ways of traversing the containers) Generic Algorithms to act on the above

The Stack A stack is a dynamic data structure which operates on the principle of Last In First Out (LIFO) It has two fundamental operations :- push - add a value to the stack pop - remove the top value from the stack [Knuth]

The Stack A stack is a dynamic data structure which operates on the principle of Last In First Out (LIFO) It has two fundamental operations :- push - add a value to the stack pop - remove the top value from the stack [Knuth]

Stack Stacks are frequently used in computer graphics as a way of preserving a graphics state. OpenGL and Renderman both use Push and Pop operations to Save and Restore transformation information (usually a transform matrix) This allows for local and global transformations to happen within certain graphics contexts.

The Stack Stacks are also useful for doing simple calculations Using a method called Reverse Polish Notation (RPN) In Reverse Polish notation the operators follow their operands For example 3+4 can be represented by 3 4 + Using a stack we can push the values 3 and 4 onto the stack Then call an add operation which puts the sum on the top of the stack

Example

Float Stack 1 #include <iostream> 2 #include <stack> 3 4 int main(void) 5 { 6 // create a stack of floats 7 std::stack <float> FloatStack; 8 // push some values on the stack 9 FloatStack.push(3.0); 10 FloatStack.push(2.0); 11 // get the size of the stack 12 std::cout <<"Stack Size = "<<FloatStack.size()<<std::endl; 13 // print the top value 14 std::cout <<"top "<<FloatStack.top()<<std::endl; 15 // pop the value from the top of the stack 16 FloatStack.pop(); 17 std::cout <<"top "<<FloatStack.top()<<std::endl; 18 } <float> indicates to use a float template for the stack push some values on the stack The size() method returns the size of the stack

Linked Lists A Linked list is a classic computer data structure It consists of a number of linked nodes (structures) where each node points to another one. The lists may be implemented in a number of different ways Many modern languages have these data structures built into the core language, however C does not so we have to implement them ourselves.

Linked list types 15 8 12 null Single linked list, each node points to the next Start null 15 8 12 null End A double linked list has references to previous and next values in the list 15 8 12 A circular list points back to the beginning of the list (so never ends) good for buffers etc.

Typical Linked list Operations insert at beginning of list insert at end of list insert in order (of data / priority ) search remove contents

std::list <T> List containers are implemented as doubly-linked lists; Doubly linked lists can store each of the elements they contain in different and unrelated storage locations. The ordering is kept by the association to each element of a link to the element preceding it and a link to the element following it.

Advantages of std::list This provides the following advantages to list containers: Efficient insertion and removal of elements anywhere in the container (constant time). Efficient moving elements and block of elements within the container or even between different containers (constant time). Iterating over the elements in forward or reverse order (linear time). Compared to other base standard sequence containers (vectors and deques), lists perform generally better in inserting, extracting and moving elements in any position within the container, and therefore also in algorithms that make intensive use of these, like sorting algorithms.

std::list methods empty() Test whether container is empty (public member function) size() Return size (public member function) max_size() Return maximum size (public member function) resize() Change size (public member function)

stl::list methods front() Access first element (public member function) back() Access last element (public member function) assign() Assign new content to container (public member function) push_front() pop_front() push_back() pop_back() insert() erase() swap() clear() Insert element at beginning (public member function) Delete first element (public member function) Add element at the end (public member function) Delete last element (public member function) Insert elements (public member function) Erase elements (public member function) Swap content (public member function) Clear content (public member function)

1 #include <list> 2 3 4 int main(void) 5 { 6 std::list <float> ToSort; 7 8 ToSort.push_back(2.0); 9 ToSort.push_back(9.0); 10 ToSort.push_back(2.1); 11 ToSort.push_front(12.0); 12 ToSort.push_front(3.0); 13 ToSort.push_front(3.0); 14 15 PrintList(ToSort); 16 ToSort.sort(); 17 std::cout <<"Sorted"<<std::endl; 18 PrintList(ToSort); 19 std::cout <<"reverse" <<std::endl; 20 ToSort.reverse(); 21 PrintList(ToSort); 22 23 std::cout <<"Front method "<<ToSort.front()<<std::endl; 24 std::cout <<"Back method "<<ToSort.back()<<std::endl; 25 std::cout << "Clear List"<<std::endl; 26 27 std::cout <<"Add some more values "<<std::endl; 28 ToSort.push_front(12.0); 29 ToSort.push_front(3.0); 30 ToSort.push_front(3.0); 31 PrintList(ToSort); 32 33 std::cout <<"Now remove unique values"<<std::endl; 34 ToSort.unique(); 35 PrintList(ToSort); 36 37 38 ToSort.clear(); 39 PrintList(ToSort); 40 return EXIT_SUCCESS; 41 } float list Include the list header Create a list of floats use push_back and push_front methods to fill the list Call methods to manipulate the List

std::list<t>::iterator Iterators know about the internal structure of the object they are associated with They are allow use to traverse the unknown internal structure of the container and gain access to the elements. Iterators are usually defined as functions such as begin / end or the reverse iterators rbegin / rend This iterator can modify the list

std::list<t>::const_iterator The const_iterator allows read only access to the data contained in the list. In the next example we pass the list by const reference so we need to use the const_iterator.

std::begin().begin() std::end().end() std::begin() and std::end() are c++ 11 only

std::rbegin().rbegin() std::rend().rend() std::rbegin() and std::rend() are c++ 11 only

Preferred method 1 void PrintList( 2 const std::list <float> &_l 3 ) 4 { 5 std::list <float>::const_iterator begin=_l.begin(); 6 std::list <float>::const_iterator end=_l.end(); 7 std::cout <<"******"<<std::endl; 8 while(begin!= end) 9 { 10 std::cout <<*begin++<<std::endl; 11 } 12 std::cout <<"******"<<std::endl; 13 } Boost method Slower method iterating a list to print 1 void PrintList( 2 const std::list <float> &_l 3 ) 4 { 5 std::cout <<"******"<<std::endl; 6 BOOST_FOREACH(float f,_l) 7 { 8 std::cout <<f<<std::endl; 9 } 10 std::cout <<"******"<<std::endl; 11 } 1 void PrintList( 2 const std::list <float> &_l 3 ) 4 { 5 std::list <float>::const_iterator it; 6 std::cout <<"******"<<std::endl; 7 for(it = _l.begin(); it!=_l.end(); ++it) 8 { 9 std::cout <<*it<<std::endl; 10 } 11 std::cout <<"******"<<std::endl; 12 13 }

Dynamic Array We can think of the dynamic array as a special case of a linked list It uses the same type of operations as a linked list but we can treat it as a normal array

Dynamic Array C++ has a dynamic array object called a Vector as part of the Standard Template Library (STL) Vectors are good at: Accessing individual elements by their position index (constant time). Iterating over the elements in any order (linear time). Add and remove elements from its end (constant amortized time). Compared to arrays, they provide almost the same performance for these tasks, plus they have the ability to be easily resized. Although, they usually consume more memory than arrays when their capacity is handled automatically (this is in order to accommodate for extra storage space for future growth).

std::vector<t> 1 #ifndef POINT3_H 2 #define POONT3_H 3 #include <iostream> 4 #include <cassert> 5 6 class Point3 7 { 8 9 public : 10 11 friend std::ostream& operator<<( 12 std::ostream& _output, 13 const Point3& _s 14 ) 15 { 16 return _output<<"["<<_s.m_x<<","<<_s.m_y<<","<<_s.m_z<<"]"; 17 } 18 19 inline Point3(float _x, float _y, float _z): m_x(_x),m_y(_y),m_z(_z){;} 20 21 inline float& operator[]( 22 const int& _i 23 ) 24 { 25 assert(_i >=0 _i<=3); 26 return (&m_x)[_i]; 27 } 28 29 private : 30 float m_x; 31 float m_y; 32 float m_z; 33 34 35 }; 36 37 #endif 1 #include <iostream> 2 #include <vector> 3 #include <cstdlib> 4 #include <boost/foreach.hpp> 5 #include "Point3.h" 6 7 8 int main(void) 9 { 10 std::vector <Point3> PointList; 11 12 for (int i=0; i<10; ++i) 13 { 14 PointList.push_back(Point3(i,i,i)); 15 } 16 // we can access elements like a normal array 17 PointList[0][0]=99; 18 PointList[0][1]=99; 19 PointList[0][2]=99; 20 21 22 BOOST_REVERSE_FOREACH(Point3 p, PointList) 23 { 24 std::cout <<p<<std::endl; 25 } 26 return EXIT_SUCCESS; 27 }

containers with pointers We can clear the contents of a container by using the.clear or erase methods This will remove and call the dtor on any automatic object However this is not true for dynamic objects. Where we must first delete the object pointed to then clear the container The following example shows this.

automatic scoped std::vector auto ctor { ctor std::cout<<"scoped std::vector auto\n" ; Mem a(10); Mem b(10); std::vector<mem>v; v.push_back(a); v.push_back(b); } std::cout<<"end auto scope\n"; copy ctor copy ctor copy ctor dtor dtor dtor dtor dtor end auto scope

dynamic { std::cout<<"scoped std::vector dynamic \n"; std::vector<mem *>v; v.push_back(new Mem(10)); scoped std::vector dynamic ctor ctor end dynamic scope v.push_back(new Mem(10)); v.clear(); } std::cout<<"end dynamic scope\n";

delete dynamic { std::cout<<"scoped std::vector dynamic with delete\n"; std::vector<mem *>v; v.push_back(new Mem(10)); v.push_back(new Mem(10)); for(size_t i=0; i<v.size(); ++i) delete v[i]; v.clear(); } std::cout<<"end dynamic scope\n"; scoped std::vector dynamic with delete ctor ctor dtor dtor end dynamic scope

smart pointer { std::cout<<"shared pointer\n"; std::vector<boost::shared_ptr<mem > >v; v.push_back( boost::shared_ptr<mem >(new Mem(10)) ); v.push_back( boost::shared_ptr<mem >(new Mem(10)) ); v.clear(); } std::cout<<"end smart pointer scope\n"; smart pointer ctor ctor dtor dtor end smart pointer scope

std::map<t> std::unordered_map<t> (c++11) Maps are a kind of associative containers that stores elements formed by the combination of a key value and a mapped value. In a map, the key value is generally used to uniquely identify the element, while the mapped value is some sort of value associated to this key. Types of key and mapped value may differ. For example, a typical example of a map is a telephone guide where the name is the key and the telephone number is the mapped value. Internally, the elements in the map are sorted from lower to higher key value following a specific strict weak ordering criterion set on construction. unordered_map uses a hash function As associative containers, they are especially designed to be efficient accessing its elements by their key (unlike sequence containers, which are more efficient accessing elements by their relative or absolute position).

std::vector<t> 1 #ifndef POINT3_H 2 #define POONT3_H 3 #include <iostream> 4 #include <cassert> 5 6 class Point3 7 { 8 9 public : 10 11 friend std::ostream& operator<<( 12 std::ostream& _output, 13 const Point3& _s 14 ) 15 { 16 return _output<<"["<<_s.m_x<<","<<_s.m_y<<","<<_s.m_z<<"]"; 17 } 18 19 inline Point3(float _x, float _y, float _z): m_x(_x),m_y(_y),m_z(_z){;} 20 21 inline float& operator[]( 22 const int& _i 23 ) 24 { 25 assert(_i >=0 _i<=3); 26 return (&m_x)[_i]; 27 } 28 29 private : 30 float m_x; 31 float m_y; 32 float m_z; 33 34 35 }; 36 37 #endif 1 #include <iostream> 2 #include <vector> 3 #include <cstdlib> 4 #include <boost/foreach.hpp> 5 #include "Point3.h" 6 7 8 int main(void) 9 { 10 std::vector <Point3> PointList; 11 12 for (int i=0; i<10; ++i) 13 { 14 PointList.push_back(Point3(i,i,i)); 15 } 16 // we can access elements like a normal array 17 PointList[0][0]=99; 18 PointList[0][1]=99; 19 PointList[0][2]=99; 20 21 22 BOOST_REVERSE_FOREACH(Point3 p, PointList) 23 { 24 std::cout <<p<<std::endl; 25 } 26 return EXIT_SUCCESS; 27 }

std::map<t> std::unordered_map<t> (c++11) Maps are a kind of associative containers that stores elements formed by the combination of a key value and a mapped value. In a map, the key value is generally used to uniquely identify the element, while the mapped value is some sort of value associated to this key. Types of key and mapped value may differ. For example, a typical example of a map is a telephone guide where the name is the key and the telephone number is the mapped value. Internally, the elements in the map are sorted from lower to higher key value following a specific strict weak ordering criterion set on construction. unordered_map uses a hash function As associative containers, they are especially designed to be efficient accessing its elements by their key (unlike sequence containers, which are more efficient accessing elements by their relative or absolute position).

String Map 1 #include <iostream> 2 #include <map> 3 #include <string> 4 #include <cstdlib> 5 6 int main(void) 7 { 8 std::map <std::string,int> MyMap; 9 10 MyMap["Jon"]=120212442; 11 MyMap["Office"]=123331452; 12 MyMap["Land Line"]=243464343; 13 14 std::cout <<MyMap["Jon"]<<std::endl; 15 std::cout <<MyMap["Land Line"]<<std::endl; 16 std::cout <<MyMap["Office"]<<std::endl; 17 MyMap["Jon"]=442; 18 std::cout <<MyMap["Jon"]<<std::endl; 19 return EXIT_SUCCESS; 20 }

Function Map Here we grab the address of the Function When it is called this is used to call the function 1 #include <iostream> 2 #include <map> 3 #include <string> 4 #include <cstdlib> 5 6 7 void FuncA( 8 int _value 9 ) 10 { 11 std::cout <<"Function A "<<_value<<std::endl; 12 } 13 14 void FuncB( 15 int _value 16 ) 17 { 18 std::cout <<"Function B "<<_value<<std::endl; 19 } 20 21 void FuncC( 22 int _value 23 ) 24 { 25 std::cout <<"Function C "<<_value<<std::endl; 26 } 27 28 int main() 29 { 30 std::map <std::string,void (*)(int)> MyMap; 31 32 MyMap["run"]=&FuncA; 33 MyMap["walk"]=&FuncB; 34 MyMap["fire"]=&FuncC; 35 36 MyMap["run"](56); 37 MyMap["fire"](10); 38 MyMap["walk"](1); 39 return EXIT_SUCCESS; 40 }

Problems with std::map If we lookup a key using [] that doesn t have a value map will insert one This can lead to errors and overflows as show in the following example We should always use the iterators and.find methods for a lookup of the key We can access the value stored using the ->second value (and - >first) for the key.

#include <iostream> #include <cstdlib> #include <map> #include <string> int main() { std::map<int,std::string> map; map[0]="this is a value"; std::cout<<map.size()<<"\n"; for(int i=1; i<20; ++i) { std::cout<<map[i]<<" "<<map.size()<<"\n"; } map.clear(); map[0]="reset"; for(int i=0; i<20; ++i) { std::cout<<"size "<<map.size()<<"\n"; std::map <int,std::string>::const_iterator it=map. find(i); if(it!=map.end()) { std::cout<<"found value "<<it->second<<"\n"; } } } return EXIT_SUCCESS;

The algorithm Library #include <algorithm> defines a collection of functions that operate on containers with range based elements (have iterators) These algorithms operate on the values stored in the container They will never increase the size of the container just modify the contents It is also possible to use these algorithms on our own containers as long as the container satisfies the conditions of the algorithm (usually overloaded operators for compare and access)

std::for_each Applies a function to a range #include <iostream> #include <list> #include <algorithm> #include <string> void printfunc(std::string i) { std::cout<<i<<"\n"; } int main() { std::list <std::string> mylist; mylist.push_back("2"); mylist.push_back("asdasd4"); mylist.push_back("asd"); mylist.push_back("skdfjhsdfkjhkj"); mylist.push_back("sdfsdhfkjsdhf"); std::for_each(mylist.begin(),mylist.end(), printfunc); std::cout<<"2 appears "<<std::count(mylist. begin(),mylist.end(),"asd")<<"times\n"; }

std::count_if #include <iostream> #include <algorithm> #include <vector> bool isodd (int i) { return ((i%2)==1); } returns the number of elements in the range for which the condition is true int main () { int mycount; std::vector<int> myvector; for (int i=0; i<10; ++i) myvector.push_back(i); mycount = (int) std::count_if (myvector. begin(), myvector.end(), isodd); std::cout << "myvector contains " << mycount << " odd values.\n"; } return 0;

std::generate generate values within a range #include <iostream> #include <vector> #include <algorithm> #include <cstdlib> int randnum() { return rand()%100; } void printfunc(int i) { std::cout<<i<<"\n"; } int main() { } std::vector <int> randomnumbers; randomnumbers.resize(5); std::generate(randomnumbers.begin(),randomnumbers.end(),randnum); std::for_each(randomnumbers.begin(),randomnumbers.end(),printfunc); std::cout<<"*********\n"; std::for_each(randomnumbers.rbegin(),randomnumbers.rend(),printfunc);

std::random_shuffle Rearranges the elements in the range randomly. #include <iostream> #include <vector> #include <algorithm> void printfunc(int i) { std::cout<<i<<"\n"; } int main() { } std::vector <int> data; for(int i=0; i<20; ++i) data.push_back(i); std::for_each(data.begin(),data.end(),printfunc); std::random_shuffle(data.begin(),data.end()); std::cout<<"shuffle\n"; std::for_each(data.begin(),data.end(),printfunc);

std::transform apply a function in a range #include <iostream> #include <list> #include <algorithm> void printfunc(int i) { std::cout<<i<<"\n"; } int Double(int i) { return i*2;} int main() { std::list <int> mylist; mylist.push_back(2); mylist.push_back(4); mylist.push_back(5); mylist.push_back(6); mylist.push_back(2); std::list <int> secondlist; secondlist.resize(mylist.size()); std::for_each(mylist.begin(),mylist.end(),printfunc); std::transform(mylist.begin(),mylist.end(),secondlist.begin(),double); std::cout<<"second\n"; std::for_each(secondlist.begin(),secondlist.end(),printfunc); }

std::make_heap Rearranges the elements in the range in such a way that they form a heap. #include <iostream> #include <vector> #include <algorithm> void printfunc(int i) { std::cout<<i<<"\n"; } int main() { std::vector <int> data; data.push_back(2); data.push_back(4); data.push_back(5); data.push_back(6); data.push_back(2); std::for_each(data.begin(),data.end(),printfunc); std::make_heap (data.begin(),data.end()); std::cout << "max heap : " << data.front() << std::endl; std::sort_heap (data.begin(),data.end()); std::for_each(data.begin(),data.end(),printfunc); std::cout<<"doing push back\n"; data.push_back(99); std::push_heap (data.begin(),data.end()); std::for_each(data.begin(),data.end(),printfunc); }

Knuth D.E. The art of Computer Programming Vol 1 Addison Wesley http://www.cppreference.com/wiki/stl/start http://www.cplusplus.com/reference/stl/list/ http://www.cplusplus.com/reference/stl/bitset/ http://www.cplusplus.com/reference/stl/vector/ http://www.cplusplus.com/reference/stl/map/ http://en.wikipedia.org/wiki/linked_list#linked_list_operations