gdc roadtrip dec 1999 embracing the c++ stl: why angle brackets are good for you pete isensee

59
GDC Roadtrip Dec 1999 Embracing the C++ STL: Embracing the C++ STL: Why Angle Brackets are Why Angle Brackets are Good for You Good for You Pete Isensee Pete Isensee

Upload: randell-lang

Post on 22-Dec-2015

220 views

Category:

Documents


0 download

TRANSCRIPT

GDC Roadtrip Dec 1999

Embracing the C++ STL:Embracing the C++ STL:Why Angle Brackets areWhy Angle Brackets areGood for YouGood for You

Pete IsenseePete Isensee

GDC Roadtrip Dec 1999

IntroductionIntroduction STL Background & HistorySTL Background & History Key ConceptsKey Concepts Containers, Iterators and Containers, Iterators and

AlgorithmsAlgorithms Efficiency and Thread SafetyEfficiency and Thread Safety Tips and TricksTips and Tricks

GDC Roadtrip Dec 1999

GoalsGoals STL NewbieSTL Newbie

– Convince you that it’s a “good thing”Convince you that it’s a “good thing”– Help you avoid common mistakesHelp you avoid common mistakes

STL JunkieSTL Junkie– Add new STL techniques to your Add new STL techniques to your

toolboxtoolbox– Tricks and tipsTricks and tips

GDC Roadtrip Dec 1999

PreliminariesPreliminaries Microsoft Visual C++ 6.0Microsoft Visual C++ 6.0 Dinkumware STL implementationDinkumware STL implementation Benchmarks on Pentium III - Benchmarks on Pentium III -

550MHz550MHz Performance graphs show Performance graphs show relativerelative

performance – taller is better!performance – taller is better!

GDC Roadtrip Dec 1999

HistoryHistory Alex Stepanov & Meng Lee, based Alex Stepanov & Meng Lee, based

on earlier work by Stepanov & on earlier work by Stepanov & MusserMusser

Proposed to C++ committee late ‘93Proposed to C++ committee late ‘93 HP version released ‘94HP version released ‘94 Accepted into Standard summer ‘94Accepted into Standard summer ‘94 Standard froze ‘97, ratified ‘98Standard froze ‘97, ratified ‘98

GDC Roadtrip Dec 1999

AdvantagesAdvantages StandardizedStandardized Thin & efficientThin & efficient Little inheritance; no virtual Little inheritance; no virtual

functionsfunctions Small; easy to learnSmall; easy to learn Flexible and extensibleFlexible and extensible Naturally open sourceNaturally open source

GDC Roadtrip Dec 1999

DisadvantagesDisadvantages Template syntaxTemplate syntax Difficult to read & decipherDifficult to read & decipher Poor or incomplete compiler Poor or incomplete compiler

supportsupport Code bloat potentialCode bloat potential No constraints on template typesNo constraints on template types Limited container typesLimited container types

GDC Roadtrip Dec 1999

Key ConceptsKey Concepts Generic Generic algorithmsalgorithms ContainerContainer classes classes IteratorsIterators : “container walkers” for : “container walkers” for

accessing container elementsaccessing container elements Iterators provide an abstraction of Iterators provide an abstraction of

container access, which in turn container access, which in turn allows for generic algorithmsallows for generic algorithms

Iterator invalidationIterator invalidation

GDC Roadtrip Dec 1999

Key Concepts (cont.)Key Concepts (cont.) Ranges: C/C++ “past-the-end” pointerRanges: C/C++ “past-the-end” pointer

T Wallace[N];T Wallace[N];T* p = (Wallace + N); T* p = (Wallace + N); // valid pointer// valid pointerT w = *(Wallace + N); T w = *(Wallace + N); // invalid dereference// invalid dereference

c.begin() == (Wallace); c.begin() == (Wallace); // first element// first elementc.end() == (Wallace + N); c.end() == (Wallace + N); // valid iterator// valid iterator*c.end(); *c.end(); // invalid dereference// invalid dereference

end() - begin() = size()end() - begin() = size() if (begin() == end()) container is emptyif (begin() == end()) container is empty for (iter i = begin(); i != end() ++i)for (iter i = begin(); i != end() ++i)

GDC Roadtrip Dec 1999

Key Concepts (cont.)Key Concepts (cont.) Linear search exampleLinear search example

template <class InputItr, class T> InputItrtemplate <class InputItr, class T> InputItrfindfind(InputItr bg, InputItr end, const T& val)(InputItr bg, InputItr end, const T& val){ while (bg { while (bg !=!= end && end && **bg bg !=!= val) val) ++++bg;bg; return (bg); }return (bg); }

const int nSize = 4;const int nSize = 4;int Gromit[nSize] = { 5, 18, 23, 9 };int Gromit[nSize] = { 5, 18, 23, 9 };int* pFind = int* pFind = findfind(Gromit, Gromit + nSize, 23);(Gromit, Gromit + nSize, 23);

vector<int> Preston;vector<int> Preston;vector<int>::iterator i = vector<int>::iterator i = findfind(Preston.begin(), Preston.end(), 4);(Preston.begin(), Preston.end(), 4);

GDC Roadtrip Dec 1999

Putting the STL into ActionPutting the STL into Action Include files have no “.h”Include files have no “.h” Standard namespaceStandard namespace

#include <cstdio>#include <cstdio> // new include method// new include method#include <vector>#include <vector> // vector container// vector container#include <algorithm>#include <algorithm> // STL algorithms// STL algorithmsusing namespace std;using namespace std; // assume std::// assume std::

vector<int> Chuck;vector<int> Chuck; // declare a growable array// declare a growable arrayChuck.push_back(1);Chuck.push_back(1); // add an element// add an elementfind(Chuck.begin(), Chuck.end(), 1);find(Chuck.begin(), Chuck.end(), 1);

GDC Roadtrip Dec 1999

ContainersContainers Containers Containers containcontain elements; they elements; they

“own” the objects“own” the objects Containers provide iterators that Containers provide iterators that

point to its elements.point to its elements. Containers provide a minimal set Containers provide a minimal set

of operations for manipulating of operations for manipulating elementselements

GDC Roadtrip Dec 1999

Containers (cont.)Containers (cont.)Container Description Keys

vector dynamic arraydeque dynamic array -- both endslist linked listset sorted list of keys no duplicate keysmap sorted list of key and value pairs no duplicate keysmultiset sorted list of keys duplicate keys OKmultimap sorted list of key and value pairs duplicate keys OK

Minimum container object requirementsMinimum container object requirements

X() X() // default ctor// default ctorX(const X&) X(const X&) // copy ctor// copy ctorX& operator = (const X&) X& operator = (const X&) // assignment op// assignment opbool operator < (const X&) bool operator < (const X&) // comparison op// comparison opbool operator == (const X&) bool operator == (const X&) // comparison op// comparison op

GDC Roadtrip Dec 1999

VectorVector Dynamic arrayDynamic array Fast ins/erase from end of vectorFast ins/erase from end of vector reserve(), capacity()reserve(), capacity() Contiguous block of memoryContiguous block of memory Obliged to grow by some factor (2x) Obliged to grow by some factor (2x)

when size() exceeds capacity()when size() exceeds capacity() Insert invals all iters if capacity Insert invals all iters if capacity

change; insert/erase invals all iters change; insert/erase invals all iters followingfollowing

GDC Roadtrip Dec 1999

DequeDeque Double-ended queue (“deck”)Double-ended queue (“deck”) Fast ins/erase at begin Fast ins/erase at begin andand end end Directory array of pointers to nodes, Directory array of pointers to nodes,

where each node is small array of Twhere each node is small array of T Insert invals all iters; erase in Insert invals all iters; erase in

middle invals all; erase at begin/end middle invals all; erase at begin/end on invals iter to begin/endon invals iter to begin/end

GDC Roadtrip Dec 1999

ListList Doubly-linked listDoubly-linked list Fast insert/erase; no random Fast insert/erase; no random

accessaccess Special functions: splice(), merge()Special functions: splice(), merge() Erase invals iters to erased Erase invals iters to erased

elements; insert never invals any elements; insert never invals any itersiters

GDC Roadtrip Dec 1999

SetSet List of sorted elementsList of sorted elements Fast retrieval based on key (log N)Fast retrieval based on key (log N) Fast insert/erase (log N)Fast insert/erase (log N) Red-black tree (balanced 2-3-4 Red-black tree (balanced 2-3-4

tree)tree) Erase invals erased elems; insert Erase invals erased elems; insert

never invals any itersnever invals any iters

GDC Roadtrip Dec 1999

MapMap Dictionary of sorted elementsDictionary of sorted elements List of sorted key and value pairsList of sorted key and value pairs Same implementation and Same implementation and

characteristics of set containercharacteristics of set container

GDC Roadtrip Dec 1999

Container AdaptorsContainer Adaptors

Example adapator codeExample adapator code

stack<intstack<int, deque<int>, deque<int> > TechnoTrousers; > TechnoTrousers;TechnoTrousers.push(1);TechnoTrousers.push(1);int i = TechnoTrousers.top();int i = TechnoTrousers.top();TechnoTrousers.pop();TechnoTrousers.pop();

Adaptor Example containers Default container

stack list, deque, vector dequequeue list, deque dequepriority_queue list, deque, vector vector

GDC Roadtrip Dec 1999

What’s Missing?What’s Missing? stack-based arrays (T a[N])stack-based arrays (T a[N]) hash tableshash tables singly-linked listssingly-linked lists some STL implementations include some STL implementations include

one or more of these “non-one or more of these “non-standard” containersstandard” containers

GDC Roadtrip Dec 1999

Container EfficiencyContainer Efficiency

Overhead is approx. per-element size in bytesOverhead is approx. per-element size in bytes Hash and slist containers included for comparison only. Hash and slist containers included for comparison only.

C/N indicates best/worst case timesC/N indicates best/worst case times

Container Overhead Insert Erase [] Find Sortlist 8 C C n/a N N log Ndeque 12 C at begin or

end; else N/2C at begin orend; else N

C N N log N

vector 0 C at end; else N C at end; else N C N N log Nset 12 log N log N n/a log N Cmultiset 12 log N d log (N+d) n/a log N Cmap 16 log N log N log N log N Cmultimap 16 log N d log (N+d) log N log N Cstack n/a C C n/a n/a n/aqueue n/a C C n/a n/a n/apriority_queue

n/a log N log N n/a n/a n/a

slist (SGI) 4 C C n/a N n/ahashset (SGI) ? C/N C/N n/a C/N n/ahashmap(SGI)

? C/N C/N n/a C/N n/a

GDC Roadtrip Dec 1999

IteratorsIterators

Typical iterationTypical iteration

c<T>::iterator i;c<T>::iterator i;for (i = c.begin(); i != c.end() ++i) for (i = c.begin(); i != c.end() ++i) // forward// forward T t = *i;T t = *i;

for (i = c.rbegin(); i != c.rend() ++i) for (i = c.rbegin(); i != c.rend() ++i) // backward// backward T t = *i;T t = *i;

Type Valid expressions ExampleInput *t, ++i, i++, *i++ find() (read-only)Output *x = t, *x++ = t, ++x, x++ insert_iterator<C> (write-only)Forward ++i, i++, *x=t slist<T>::iterator (SGI-specific)Bidirectional ++i, i++, --i, i--, *x=t list<T>::iteratorRandom Bidrect’l, i += n, i + n, i -= n, i – n,

i[n], i[n] = tvector<T>::iterator, deque<T>::iterator

GDC Roadtrip Dec 1999

AlgorithmsAlgorithms Approx. 60 standard algorithmsApprox. 60 standard algorithms

– searching (e.g. find())searching (e.g. find())– sorting (e.g. sort())sorting (e.g. sort())– mutating (e.g. transform())mutating (e.g. transform())– numerical (e.g. accumulate())numerical (e.g. accumulate())

Most functions take the form:Most functions take the form:– fn(c.begin(), c.end(), ...)fn(c.begin(), c.end(), ...)

GDC Roadtrip Dec 1999

Algorithms (cont.)Algorithms (cont.) Examples:Examples:

#include <algorithm>#include <algorithm>

// return num elements equal to 123// return num elements equal to 123int i = int i = countcount(c.begin(), c.end(), 123);(c.begin(), c.end(), 123);

// negate all elements// negate all elementstransformtransform(c.begin(), c.end(), negate<int>());(c.begin(), c.end(), negate<int>());

// print all elements// print all elementsfor_eachfor_each(c.begin(), c.end(), print<int>());(c.begin(), c.end(), print<int>());

// shuffle the deck// shuffle the deckrandom_shufflerandom_shuffle(deck.begin(), deck.end());(deck.begin(), deck.end());

GDC Roadtrip Dec 1999

Function Objects Function Objects (Functors)(Functors)

C++ objects that can be called like C++ objects that can be called like a function to implement a function to implement “callbacks”“callbacks”

Use C++ operator()(...)Use C++ operator()(...) Simplest type is a function pointerSimplest type is a function pointer

bool bool StlStrCompStlStrComp(const char* a, const char* b)(const char* a, const char* b) { return (strcmp(a, b) == -1); }{ return (strcmp(a, b) == -1); }

vector<char*> v;vector<char*> v;sort(v.begin(), v.end(), sort(v.begin(), v.end(), StlStrCompStlStrComp););

GDC Roadtrip Dec 1999

Functors (cont.)Functors (cont.) Functors that do ordering are Functors that do ordering are

called “predicates”called “predicates”

struct struct StlStrPred StlStrPred // “public” class// “public” class{ bool operator()(const char* a, const char* b){ bool operator()(const char* a, const char* b) { return (strcmp(a, b) == -1); } };{ return (strcmp(a, b) == -1); } };

vector<char*> v;vector<char*> v;sort(v.begin(), v.end(), sort(v.begin(), v.end(), StlStrPred()StlStrPred()););

GDC Roadtrip Dec 1999

EfficiencyEfficiency Designed to be as fast as hand-Designed to be as fast as hand-

coded routinescoded routines Limiting factor is typically copy Limiting factor is typically copy

ctor and assignment operatorctor and assignment operator

GDC Roadtrip Dec 1999

Efficiency (cont.)Efficiency (cont.) STL STL fasterfaster in some cases than in some cases than

standard C functionsstandard C functions

const char* WestWallaby = “Gromit”;const char* WestWallaby = “Gromit”;strchrstrchr(WestWallaby, ‘m’);(WestWallaby, ‘m’);findfind(WestWallaby, WestWallaby+6, ‘m’);(WestWallaby, WestWallaby+6, ‘m’);

GDC Roadtrip Dec 1999

Efficiency (cont.)Efficiency (cont.) Sorting (ints)Sorting (ints)

int arr[nElements];

qsort(arr, nElements, sizeof(int), IntComp);

int arr[nElements];

sort(arr, arr + nElements); // STL int array sort

vector<int> v;

sort(v.begin(), v.end()); // STL int vector sort

GDC Roadtrip Dec 1999

Efficiency (cont.)Efficiency (cont.) Sorting (strings)Sorting (strings)

char* arr[nElements];

qsort(arr, nElements, sizeof(char*), StrComp);

sort(arr, arr + nElements, StlStrComp);

sort(v.begin(), v.end(), StlStrComp); // char*

sort(v.begin(), v.end(), StlStrComp); // string

GDC Roadtrip Dec 1999

STL AllocatorsSTL Allocators Every STL container takes an Every STL container takes an

allocator object as a template allocator object as a template parameterparametertemplate <class T> public AllocSpecialCheesetemplate <class T> public AllocSpecialCheese{ public:{ public: pointer allocate(size_type, const void*);pointer allocate(size_type, const void*); void deallocate(void*, size_type); void deallocate(void*, size_type); // ... other boilerplate code here// ... other boilerplate code here};};

set<int> Camembert; set<int> Camembert; // default allocator// default allocator

// All Wensleydale allocations use special allocator// All Wensleydale allocations use special allocatorset<int, AllocSpecialCheese> Wensleydale;set<int, AllocSpecialCheese> Wensleydale;

GDC Roadtrip Dec 1999

Template Partial Template Partial SpecializationSpecialization

// generic template function for swapping objects// generic template function for swapping objectstemplate <class T> void swap(T& x, T& y)template <class T> void swap(T& x, T& y) { T z(x); x = y; y = z; }{ T z(x); x = y; y = z; }

swap(v1, v2); swap(v1, v2); // swapping vectors: slow!// swapping vectors: slow!v1.swap(v2); v1.swap(v2); // swapping vectors: fast!// swapping vectors: fast!

// template partial specialization// template partial specializationtemplate <class T> void swap(template <class T> void swap(vector<T>vector<T>& x,& x, vector<T>vector<T>& y)& y) { x.swap(y); }{ x.swap(y); }

swap(v1, v2); swap(v1, v2); // fast!// fast!

GDC Roadtrip Dec 1999

Template Specialization part Template Specialization part II II

// STL generic copy() algorithm

template<class InItr, class OutItr> OutItr

copy(InItr bg, InItr end, OutItr val)

{ for (; bg != end; ++val, ++bg)

*val = *bg;

return (val); }

// A fast version for simple memory chunks

template<> char* copy(const char* bg,

const char* end, char* val)

{ size_t n = end - bg;

memcpy(val, bg, n);

return (val + n); }

GDC Roadtrip Dec 1999

Thread SafetyThread Safety Official answer: STL has no thread Official answer: STL has no thread

safety obligations whatsoeversafety obligations whatsoever One (bad) answer: have STL handle One (bad) answer: have STL handle

all synchronization issuesall synchronization issues Typical answer: make STL thread Typical answer: make STL thread

safe internally, but require users to safe internally, but require users to insure no thread accesses a insure no thread accesses a container when another thread container when another thread modifies the containermodifies the container

GDC Roadtrip Dec 1999

Thread Safety (cont.)Thread Safety (cont.) Current status of implementationsCurrent status of implementations

– Original HP version Original HP version notnot thread safe thread safe– SGI thread safeSGI thread safe– VC VC mostlymostly thread safe thread safe (dinkumware.com/vc_fixes.html)(dinkumware.com/vc_fixes.html)

Typical STL implementation promisesTypical STL implementation promises– Multiple reads is thread safeMultiple reads is thread safe– Read/write across different containers, same Read/write across different containers, same

objects, is thread safeobjects, is thread safe– Writes to a container by one thread and Writes to a container by one thread and

read/writes by another thread is read/writes by another thread is notnot thread safe; thread safe; users must preventusers must prevent

GDC Roadtrip Dec 1999

Exception SafetyException Safety C++ standard requires the followingC++ standard requires the following

– destructors may not throw excptnsdestructors may not throw excptns– valid iterator operations may not throwvalid iterator operations may not throw– containers must “survive” excptns; containers must “survive” excptns;

content unspecified, but still destructablecontent unspecified, but still destructable– an excptn thrown while inserting one an excptn thrown while inserting one

element leaves the container unchangedelement leaves the container unchanged– an excptn thrown while inserting two+ an excptn thrown while inserting two+

elements leaves a elements leaves a listlist unchanged unchanged

GDC Roadtrip Dec 1999

Code BloatCode Bloat Templates expand into different Templates expand into different

sets of code for each type Tsets of code for each type T If different types have the same If different types have the same

size and same comparison size and same comparison functions, the compiler can functions, the compiler can optimizeoptimize

Some STL implementations are Some STL implementations are optimized to minimize code bloat optimized to minimize code bloat (XTL from DeltaLogic)(XTL from DeltaLogic)

GDC Roadtrip Dec 1999

Compiler Warnings & Compiler Warnings & ErrorsErrors

VC warning C4786: identifier VC warning C4786: identifier truncationtruncation

#pragma warning(disable: 4786) #pragma warning(disable: 4786) // before headers!// before headers!

Errors/warnings in header filesErrors/warnings in header files– really means: your code has a problemreally means: your code has a problem

Interpreting gonzo error messagesInterpreting gonzo error messages

map<string, int> m;map<string, int> m;

map<string, int>const_iterator i = m.find(“abc”);map<string, int>const_iterator i = m.find(“abc”);

m.erase(i); m.erase(i); // “big” error here// “big” error here

GDC Roadtrip Dec 1999

Compiler Errors (cont.)Compiler Errors (cont.)error C2664: 'class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char>

>,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int>,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::iterator __thiscall std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct

std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::erase(class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int>,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >

>,class std::allocator<int> >::iterator)' : cannot convert parameter 1 from 'class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int>,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class

std::allocator<char> > >,class std::allocator<int> >::const_iterator' to 'class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int>,struct std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >

>,class std::allocator<int> >::iterator'

No constructor could take the source type, or constructor overload resolution was ambiguous

GDC Roadtrip Dec 1999

Extending the STLExtending the STL Designed for extensionDesigned for extension Not difficult to write new Not difficult to write new

algorithms, containers, or iteratorsalgorithms, containers, or iterators SGI implementation has many SGI implementation has many

useful container extensions (hash useful container extensions (hash tables, slist)tables, slist)

GDC Roadtrip Dec 1999

Our own AlgorithmOur own Algorithm// Compute sum of all squares in range

template<class InItr, class T> T

sumsqrs(InItr bg, InItr end, T init)

{ T ss(init);

for (; bg != end; ++bg) { ss += (*bg) * (*bg); }

return (ss); }

int CloseShave[4] = { 1, 2, 3, 4 };

int x = sumsqrs(CloseShave, CloseShave+4, 0); // 30

deque<double> WrongTrousers; // 1.1, 2.2, 3.3

double y = sumsqrs(WrongTrousers.begin(), // 16.94

WrongTrousers.end(), 0.0);

GDC Roadtrip Dec 1999

Our own IteratorOur own Iteratortemplate <class C, class T, class A = allocator<T> >

struct MfcIt : public _Ranit<T, A::difference_type> {

C* mpC; // MFC container

int mI; // index into container

MfcIt(C* pC = 0) : mpC(pC), mI(0) {}

MfcIt(C* pC, int n) : mpC(pC), mI(n) {}

MfcIt begin() { return (MfcIt(mpC, 0)); }

MfcIt end() { return (MfcIt(mpC, mpC->GetSize())); }

T& operator * () const { return ((*mpC)[mI]); }

MfcIt& operator ++ () { if (mI < mpC->GetSize()) ++mI; else mI = 0;

return (*this); }

MfcIt operator + (difference_type n) const { MfcIt tmp = *this;

return (tmp += n); }

bool operator == (const MfcIt& i) const { return ((mI == i.mI) &&

(mpC == i.mpC)); }

bool operator < (const MfcIt& i) const { return ((mI < i.mI) && (mpC == i.mpC)); }

};

GDC Roadtrip Dec 1999

Our own Iterator (cont.)Our own Iterator (cont.) Example of using the MFC/STL Example of using the MFC/STL

iteratoriterator

// MFC container

CStringArray arr;

arr.Add("xyz");

arr.Add("abc");

// Create STL iterator from MFC container

MfcIt<CStringArray, CString> mfc(&arr);

// Sort the MFC container using an STL algorithm!

sort(mfc.begin(), mfc.end());

GDC Roadtrip Dec 1999

Common MistakesCommon Mistakes Template of templatesTemplate of templates

stack<vector<int>> GoneWrong; // need space: “> >”

Same algorithm, different containerSame algorithm, different container

sort(Marmalade.begin(), Jelly.end()) // crash!

Right iterator, wrong containerRight iterator, wrong container

list<int>::iterator i = Feathers.begin();

McGraw.erase(i); // i doesn’t point into McGraw!

GDC Roadtrip Dec 1999

Common Mistakes (cont.)Common Mistakes (cont.) Invalid iteratorInvalid iterator

vector<int>::iterator i = GrandDayOut.begin();

GrandDayOut.push_back(1); // potential realloc

TheCooker(*i); // uh-oh! i might be invalid

Adding elements with subscript opAdding elements with subscript op

vector<char> Wendolene;

Wendolene[0] = ‘W’; // crash!

Wendolene.push_back(‘W’); // the right way

GDC Roadtrip Dec 1999

Common Mistakes (cont.)Common Mistakes (cont.) Sorting problemsSorting problems

– e.g. lookups fail, a set gets duplicatese.g. lookups fail, a set gets duplicates Usually a problem with op < or op ==Usually a problem with op < or op == RulesRules

– if x<y is true, y>x is always falseif x<y is true, y>x is always false– if x<y && y<z are true, x<z is always if x<y && y<z are true, x<z is always

falsefalse– if x==y, then x<y is always falseif x==y, then x<y is always false– if !(x<y) and !(y<x), x == yif !(x<y) and !(y<x), x == y

GDC Roadtrip Dec 1999

Hiding the Angle BracketsHiding the Angle Brackets Not prettyNot pretty

// This is hard to read

map<string, int> Shaun;

Shaun.insert(pair<string, int>(“abc”, 31));

map<string, int>::iterator i = Shaun.find(“abc”);

pair<string, int> pr = *i;

pr.first; // “abc”

pr.second; // int

GDC Roadtrip Dec 1999

Hiding the Angle Brackets Hiding the Angle Brackets (cont.)(cont.)

Typedefs are your friendTypedefs are your friend

// Tuck these away in a header file

typedef map<string, int> ShaunMap;

typedef pair<string, int> ShaunPair;

typedef ShaunMap::iterator ShaunItr;

// Same code, but no more angle brackets

ShaunMap Shaun;

Shaun.insert(ShaunPair(“abc”, 31));

ShaunItr i = Shaun.find(“abc”);

ShaunPair pr = *i;

GDC Roadtrip Dec 1999

Storing Pointers in Storing Pointers in ContainersContainers

Container will Container will notnot delete the pointers delete the pointers when the container goes awaywhen the container goes away

Will sort on pointer, not what it Will sort on pointer, not what it contains, unless you tell it otherwisecontains, unless you tell it otherwise

deque<int*> Walkies; // sorted by pointer

sort(Walkies.begin(), Walkies.end());

bool intpLess(const int* a, const int* j)

{ return (*a < *b); } // sorted by int

sort(Walkies.begin(), Walkies.end(), intpLess);

GDC Roadtrip Dec 1999

Vector TipsVector Tips Use reserve() to set aside space Use reserve() to set aside space

when vector size is known in advancewhen vector size is known in advance Can I safely take the address of a Can I safely take the address of a

vector element, e.g. &v[21]?vector element, e.g. &v[21]?– According to Standard, no. According to According to Standard, no. According to

practice, yes. Standard expected to practice, yes. Standard expected to adjust.adjust.

Trimming unused spaceTrimming unused space

v.swap(vector<T>(v)); // vector, swap thyself!

GDC Roadtrip Dec 1999

Copying ContainersCopying Containers The wrong way; copy() can’t add The wrong way; copy() can’t add

elemselems

copy(v.begin(), v.end(), nv.begin()); // uh-oh

Better and bestBetter and best

nv.resize(v.size()); // size of nv matches v

copy(v.begin(), v.end(), nv.begin());

copy(v.begin(), v.end(), back_inserter(nv));

copy(m.begin(), m.end(), insert_iterator<T>

/* map and set use this method */ (nm, nm.begin());

GDC Roadtrip Dec 1999

Algorithms that Remove Algorithms that Remove ElemsElems

Algorithms by themselves can’t Algorithms by themselves can’t insert or delete elements, so they insert or delete elements, so they move them!move them!

unique() moves unique elems to the unique() moves unique elems to the front and returns an iter to the new front and returns an iter to the new “end” of the container“end” of the container

remove() similarly moves the remove() similarly moves the “unremoved” elems to the front and “unremoved” elems to the front and returns an iter to the new “end”returns an iter to the new “end”

GDC Roadtrip Dec 1999

Removing Elems (cont.)Removing Elems (cont.) To actually get rid of the extra To actually get rid of the extra

elems, you must call erase()elems, you must call erase()

// Removes duplicates and shrinks the container

v.erase(unique(v.begin(), v.end()), v.end());

// Removes the given elements and shrinks v

v.erase(remove(v.begin(), v.end(), 1), v.end());

GDC Roadtrip Dec 1999

Vectors vs C-style arraysVectors vs C-style arrays Prefer vector or deque over arraysPrefer vector or deque over arrays Don’t have to know size in Don’t have to know size in

advanceadvance Don’t have to keep track of size Don’t have to keep track of size

separatelyseparately Little loss of efficiencyLittle loss of efficiency Vector works well with legacy code Vector works well with legacy code

that expect arraysthat expect arrays

GDC Roadtrip Dec 1999

Deque vs VectorDeque vs Vector Almost identical usability Almost identical usability

characteristicscharacteristics Faster middle insertion because Faster middle insertion because

deque only needs to shift a chunkdeque only needs to shift a chunk Constant-time insertion at the frontConstant-time insertion at the front Uses memory in a more operating Uses memory in a more operating

system-friendly waysystem-friendly way Don’t need to worry about reserve()Don’t need to worry about reserve()

GDC Roadtrip Dec 1999

The “Key” RequirementThe “Key” Requirement Once a key has been inserted into Once a key has been inserted into

a container, the key should not a container, the key should not changechange

Can’t be enforced internally by the Can’t be enforced internally by the STLSTL

Example: key is a filename; Example: key is a filename; comparison is based on file comparison is based on file contentscontents

GDC Roadtrip Dec 1999

Copy() vs Memcpy()Copy() vs Memcpy() copy() works reliably with copy() works reliably with allall objects objects memcpy() unsafe on any object with a memcpy() unsafe on any object with a

copy ctorcopy ctor copy() can copy a sequence whose copy() can copy a sequence whose

length is not known in advancelength is not known in advance copy() returns an iter to the end of the copy() returns an iter to the end of the

copy; can be used as concatenation copy; can be used as concatenation tooltool

good implementation will optimizegood implementation will optimize

GDC Roadtrip Dec 1999

Wrap UpWrap Up Algorithms, Containers, IteratorsAlgorithms, Containers, Iterators Efficient, Flexible, ExtensibleEfficient, Flexible, Extensible Angle Brackets... mmmAngle Brackets... mmm

GDC Roadtrip Dec 1999

ReferencesReferences Email me: [email protected] me: [email protected] Home page: www.tantalon.comHome page: www.tantalon.com Books: Generic Programming & the Books: Generic Programming & the

STL (Austern), STL Tutorial & STL (Austern), STL Tutorial & Reference Guid (Musser)Reference Guid (Musser)

Websites: sgi.com/Technology/STL, Websites: sgi.com/Technology/STL, dinkumware.com, deltalogic.com, dinkumware.com, deltalogic.com, roguewave.com, stlport.orgroguewave.com, stlport.org