0% found this document useful (0 votes)
53 views

Introduction To C Part 2

This document provides an outline for Part 2 of an introduction to C++ tutorial. It covers compiler options, references and pointers, function overloads, generic functions, and defining classes. Compiler options allow controlling optimizations and debugging. References pass object addresses rather than copying data. Function overloading allows different implementations for different data types. Generic functions use templates to handle multiple types with single code. Classes will be discussed for defining user-defined types.

Uploaded by

nitin rakh
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
53 views

Introduction To C Part 2

This document provides an outline for Part 2 of an introduction to C++ tutorial. It covers compiler options, references and pointers, function overloads, generic functions, and defining classes. Compiler options allow controlling optimizations and debugging. References pass object addresses rather than copying data. Function overloading allows different implementations for different data types. Generic functions use templates to handle multiple types with single code. Classes will be discussed for defining user-defined types.

Uploaded by

nitin rakh
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 45

Introduction to C++: Part 2

Tutorial Outline: Part 2

 Compiler Options
 References and Pointers
 Function Overloads
 Generic Functions
 Intro to the Standard Template Library
Existing SCC Account Temporary Tutorial Account
1. Open a web browser 1. Open a web browser
2. Navigate to http://scc-ondemand.bu.edu 2. Navigate to http://scc-ondemand-2fa.bu.edu
3. Log in with your BU Kerberos Credentials 3. Log in with Tutorial Account
Click on Interactive Apps/Desktop
eclipse/2019-06

click
When your desktop is ready click Connect to Desktop
 Enter this command to create a
directory in your home folder and to
copy in tutorial files:

/net/scc2/scratch/intro_to_cpp_2.sh
Run the Eclipse software

 Enter this command to start up the Eclipse development


environment. eclipse &

 When this window appears just click the Launch button:


Compiler Options
 We’ve been working with Eclipse using a Debug build. This is determined by the options
set for the compiler.
 The g++ compiler has a vast array of options:
 https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/index.html#toc_Invoking-GCC

 The -g flag tells the compiler to add extra information to the executable to allow the
debugger to read and manipulate the program.

 Turning on optimizations makes the compiler do more work to produce code that will
execute faster.
 This is used in the Eclipse Release build.
 What happens in optimization? https://en.wikipedia.org/wiki/Optimizing_compiler
Compiler Options (for g++ 4.8.5)
 Common flags:
 -g Support for debugging. Sometimes not completely effective with (any) optimization turned
on.

 -Og Optimize but don’t do anything that will cause issues while running the debugger.

 -O, -O2, -O3 Produce optimized code. The higher numbers let the compiler try more
strategies to generate code. They are less likely to have an impact.
 Can be combined with -g but makes debugging more difficult.

 -ffast-math -funsafe-math-optimizations May produce code that does not conform to IEEE
standards for floating point computations. Try it with your program and see if it has any impact
on accuracy and/or speed.

 -march=corei7 On the SCC, allow for some special CPU instructions to be generated for
calculations in loops that may result in faster code.
Using Compiler Options

 An IDE like Eclipse will apply these for you when building.

 On the command line (for a single source file program):

Debug g++ -o my_program -g my_source.cpp

Debug with
optimizations g++ -o my_program –g -Og my_source.cpp

Release g++ -o my_program -O3 my_source.cpp


Pass by Value

main() RectangleArea1(float L, float W)


copy
float L float L

copy
float W float W

 C++ defaults to pass by value behavior when calling a function.


 The function arguments are copied when used in the function.
 Changing the value of L or W in the RectangleArea1 function does not effect their original values in
the main() function
 When passing objects as function arguments it is important to be aware that potentially large data
structures are automatically copied!
Pass by Reference
main() RectangleArea3(const float& L, const float& W)
reference
float L float L

reference
float W float W

 Pass by reference behavior is triggered when the & character is used to modify the type of the
argument.
 This is the type of behavior you see in Fortran, Matlab, Python, and others.
 Pass by reference function arguments are NOT copied. Instead the compiler sends a pointer to the
function that references the memory location of the original variable. The syntax of using the
argument in the function does not change.
 Pass by reference arguments almost always act just like a pass by value argument when writing
code EXCEPT that changing their value changes the value of the original variable!!
 The const modifier can be used to prevent changes to the original variable in main().
void does not return a value.

void RectangleArea4(const float& L, const float& W, float& area) {


area= L*W ;
}

 In RectangleArea4 the pass by reference behavior is used as a way to


return the result without the function returning a value.
 The value of the area argument is modified in the main() routine by the
function.
 This can be a useful way for a function to return multiple values in the
calling routine.
 In C++ arguments to functions can be objects…
 Example: Consider a string variable containing 1 million characters (approx. 1 MB of RAM).
 Pass by value requires a copy – 1 MB
 pass by reference requires 8 bytes!

“C makes it easy to shoot yourself in the foot; C++ makes it harder, but
when you do it blows your whole leg off.” – Bjarne Stroustrop
Rules of thumb for function/method arguments

 Basic types (int, float, etc) just pass by value unless you need to modify
values in a calling function.
 int - 4 bytes
 int& - 8 bytes (64-bit memory address)

 Pass all objects by reference.


 use the const modifier whenever appropriate to protect yourself from accidentally modifying
variables.
Tutorial Outline: Part 2

 Compiler Options
 References and Pointers
 Function Overloads
 Generic Functions
 Defining Classes
Function overloading

 The same function can be implemented float sum(float a, float b) {


multiple times with different arguments. return a+b ;
}

int sum(int a, int b) {


 This allows for special cases to be
return a+b ;
handled, or specialized behavior for }
different types.

 cout and the << operator are an example


of function overloading
 << is just a function.
Function overloading
 Overloaded functions are differentiated
by their arguments and not the return float sum(float a, float b) {
return a+b ;
type. }
 The number of arguments and their types can be
varied. int sum(int a, int b) {
return a+b ;
}
 The compiler will decide which overload
to use depending on the types of the
arguments.

 If it can’t decide a compile-time error will


occur.
C++ Templates (aka generics)
 Generic code is code that works on multiple different data types but is
only coded once.
 In C++ this is called a template.

 A C++ template is implemented entirely in a header file to define


generic classes and functions.

 The actual code is generated by the compiler wherever the template


is used in your code.
 There is NO PENALTY when your code is running!
C++ Templates (aka generics)
 Template code should be placed in header (.h) files.

 A source code file (.cpp) is not needed for template code.

 Expect longer compile times – the compiler has to do a lot more work.

 Executing code created by templates is often much faster when


compiler optimizations are turned on.
Sample template function
 The template is started with the keyword
template and is told it’ll handle a type which is // In a header file
template <typename T>
referred to as T in the code. T sum_template (T a, T b) {
 Templates can be created with multiple different return a+b ;
types, not limited to just one. }
 You don’t have to use T, any non-reserved word will
do.
// Then call the function in a
// source file:
float x=1.0 ;
 Specialize the template to the type you want to float y=2.0 ;
use. auto z=sum_template<float>(x,y) ;
An Example

 Open the project Overloads_and_templates

 This is an example of simple function overloads and a template function.

 Let’s walk through it with the debugger.


When to use function overloading and templates?

 When it makes your code easier to use, maintain, write, or debug!


 Overloads are easier to use effectively.

 Templating everything in your code does not make it better, just harder to
develop.
 Longer compiles, harder to debug, etc.

 More experienced C++ programmers should use these features where


appropriate.
Stepping back a bit

 Summary so far:
 Basics of C++ syntax
 Declaring variables
 Defining functions
 Using the IDE

 As an object-oriented language C++ supports a core set of OOP


concepts.

 Knowing these concepts help with understanding some of the underlying


design of the language and how it operates in your programs.
The formal concepts in OOP
Polymorphism

 The core concepts in addition to


classes and objects are:
 Encapsulation Encapsulation

 Inheritance
 Polymorphism OOP
 Abstraction
Inheritance

Abstraction
Core Concepts

 Encapsulation  Abstraction
 Bundles related data and functions  The hiding of members, methods,
into a class and implementation details inside of a
class.

 Inheritance
 Builds a relationship between classes  Polymorphism
to share class members and methods  The application of the same code to
multiple data types
Core Concepts in this tutorial

 Encapsulation  Abstraction
 Demonstrated by writing some  Design and setup of classes,
classes discussion of the Standard Template
Library (STL).

 Inheritance
 Write classes that inherit (re-use) the  Polymorphism
code from other classes.  Function overloading, template code,
and the STL
Tutorial Outline: Part 2

 Compiler Options
 References and Pointers
 Function Overloads
 Generic Functions
 Intro to the Standard Template Library
The Standard Template Library

 The STL is a large collection of containers and algorithms that are part of
C++.
 It provides many of the basic algorithms and data structures used in computer science.

 As the name implies, it consists of generic code that you specialize as


needed.

 The STL is:


 Well-vetted and tested.
 Well-documented with lots of resources available for help.
Containers
 There are 16 types of containers in the STL:
Container Description Container Description
array 1D list of elements. set Unique collection in a specific
order
vector 1D list of elements
multiset Elements stored in a specific
deque Double ended queue order, can have duplicates.
forward_list Linked list map Key-value storage in a specific
list Double-linked list order
multimap Like a map but values can
stack Last-in, first-out list.
have the same key.
queue First-in, first-out list. unordered_set Same as set, sans ordering
priority_queue 1st element is always the unordered_multiset Same as multisetset, sans
largest in the container ordering
unordered_map Same as map, sans ordering
unordered_multimap Same as multimap, sans
ordering
Algorithms
 There are 85+ of these.
 Example: find, count, replace, sort, is_sorted, max, min, binary_search, reverse
 Algorithms manipulate the data stored in containers but is not tied to STL containers
 These can be applied to your own collections or containers of data
 Example:
vector<int> v(3); // Declare a vector of 3 elements.
v[0] = 7;
v[1] = 3;
v[2] = v[0] + v[1]; // v[0] == 7, v[1] == 3, v[2] == 10
reverse(v.begin(), v.end()) ; // v[0] == 10, v[1] == 3, v[2] == 7

 The implementation is hidden and the necessary code for reverse() is generated from
templates at compile time.
vector<T>
 A very common and useful class in C++ is the vector class. Access it with:

#include <vector>

 Vector has many methods:


 Various constructors
 Ways to iterate or loop through its contents
 Copy or assign to another vector
 Query vector for the number of elements it contains or its backing storage size.

 Example usage: vector<float> my_vec ;


 Or: vector<float> my_vec(50) ;
vector<T>
 Hidden from the programmer is the backing store
 Object oriented design in action!

 This is how the vector stores its data internally.


Allocated for a total of M’
elements
Add some more to the vector

New memory is allocated.


Contains N elements. Given by size() method.
Old data is copied in.
New M > old M.

Allocated for a total of M


elements Old allocation is destroyed.
Given by capacity() method.
Construction and Destruction

 A special function called the  The destructor is called when an


constructor is called when an object goes out of scope.
object is created.  Example:
void function() {
 This is used to initialize an object: ClassOne c1 ;
 Load values into member variables }
 Open files
 Object c1 is created when the
 Connect to hardware, databases,
networks, etc. program reaches the first line of
the function, and destroyed when
the program leaves the function.
Scope
 Scope is the region where a variable is valid.
 Constructors are called when an object is created.
 Destructors are called automatically when a variable is out of scope.

int main() { // Start of a code block


// in main function scope
float x ; // No constructors for built-in types
ClassOne c1 ; // c1 constructor ClassOne() is called.
if (1){ // Start of an inner code block
// scope of c2 is this inner code block
ClassOne c2 ; //c2 constructor ClassOne() is called.
} // c2 destructor is called.
ClassOne c3 ; // c3 constructor ClassOne() is called.
} // leaving program, call destructors for c3 and c1 in that order
// variable x: no destructor for built-in type
Destructors

 vector<t> can hold most types of objects:


 Primitive (aka basic) types: int, float, char, etc.
 Objects: string, your own classes, file objects, etc.
 Pointers: int*, string*, etc.
 But NOT references!

 When a vector is destroyed:


 If it holds primitive types or pointers it just deallocates its backing store.
 If it holds objects it will call each object’s destructor before freeing its backing store.
vector<t> with objects
// a vector with memory preallocated to
// hold 1000 objects.
vector<MyClass> my_vec(1000);
 Select an object in a vector.
 The members and methods can be // Now make a vector with 1000 MyClass objects
// that are initialized using the MyClass constructor
accessed directly. vector<MyClass> my_vec2(1000,MyClass(arg1,arg2));

// Access an object's method.


 Elements can be accessed with my_vec2[100].some_method() ;
// Or a member
brackets and an integer starting my_vec2[10].member_integer = 100 ;
from 0.
// Clear out the entire vector
my_vec2.clear()
// but that might not re-set the backing store…
// Let’s check the docs:
// http://www.cplusplus.com/reference/vector/vector/clear/
for (int index = 0 ; index < vec.size() ; ++index)
{
// ++index means "add 1 to the value of index"
cout << vec[index] << " " ;
}
Looping

 Loop with a “for” loop, referencing the value of vec using brackets.
 1st time through:
 index = 0
 Print value at vec[0]
 index gets incremented by 1

 2nd time through:


 Index = 1
 Etc

 After last time through


 Index now equal to vec.size()
 Loop exits
 Careful! Using an out of range index will likely cause a memory error that crashes your
program.
v.begin()+1
Iterators v.begin()+2

v.begin() v.end()
v[0] v[1] v[2]

 Iterators are generalized ways of keeping track of positions in a container.


 3 types: forward iterators, bidirectional, random access
 Forward iterators can only be incremented (as seen here)
 Bidirectional can be added or subtracted to move both directions
 Random access can be used to access the container at any location
for (vector<int>::iterator itr = vec.begin(); itr != vec.end() ; ++itr)
{
cout << *itr << " " ;
// iterators are pointers!
}
Looping

 Loop with a “for” loop, referencing the value of vec using an iterator type.
 vector<int>::iterator is a type that iterates through a vector of int’s.
 1st time through:
 itr points at 1st element in vec
 Print value pointed at by itr: *itr
 itr is incremented to the next element in the vector
 Iterators are very useful C++ concepts. They work on any STL container!
 No need to worry about the # of elements!
 Exact iterator behavior depends on the type of container but they are guaranteed to always
reach every value.
for (auto itr = vec.begin() ; itr != vec.end() ; ++itr)
{
cout << *itr << " " ;
}

 Let the auto type asks the C++ compiler to figure out the iterator type automatically.
Looping

for (auto itr = vec.begin(), auto vec_end = vec.end() ; itr != vec_end ; ++itr)
{
cout << *itr << " " ;
}

 An extra modification: Assigning the vec_end variable avoids calling vec.end() on every loop.
for(const auto &element : vec)
{
cout << element << " " ;
}

 Another iterator-based loop: iterator behavior and accessing an element are handled
Looping

automatically by the compiler


 Uses a reference so the element is not copied.
 The const auto & prevents changes to the element in the vector.
 If you don’t use const then the loop can update the vector elements via the reference.

 Less typing == less chance for program bugs.


Iterator notes
 There is small performance penalty for using iterators…but are they safer to use.
 They allow substitution of one container for another (list<> for vector<>, etc.)
 With templates you can write a function that accepts any STL container type.

template<typename T>
void dump_string(T &t)
{
for( auto itr=t.begin() ; itr!=t.end() ; itr++) {
cout << *itr << endl;
}
}

list<float> lst ;
lst.push_back(-5.0) ;
lst.push_back(12.0) ;
vector<double> vec(2) ;
vec[0] = 1.0 ;
vec[1] = 2.0 ;

dump_string<list<float> >(lst) ;
dump_string<vector<double> >(lst) ;
STL Demo

 Open project STL_Demo

 Let’s walk through the functions with the debugger and see
some vectors in action.

You might also like