C++ Primer
C++ Primer
What is C++?
C++ is a general-purpose programming language with a bias towards systems programming
that:
• Is a better C
• Supports data abstraction (e.g., classes)
• Supports object-oriented programming (e.g., inheritance)
• Supports generic programming (e.g., reusable generic containers and algorithms)
• Supports functional programming (e.g., template metaprogramming, lambda functions)
2
History of C++
• Extension of C
• Early 1980s: Bjarne Stroustrup
• Supports OOP (Object Oriented Programming)
• Objects are reusable software components (attempt to model items in the real world)
• Object-oriented programs are easier to understand, correct, and modify
• C++ is a hybrid language
• C-style programming
• OOP-style
• Standardized
ISO International Standard ISO/IEC 14882:2014(E) – Programming Language C++
• Current standard: C++14
• Working draft: C++17
3
Object-oriented programming (OOP)
• OOP is a methodology for organizing data and functions
• In OOP, functions (called methods) are attached/associated with the data (objects)
(whereas in procedural-based programming, functions act on data)
• In OOP, functions can only be invoked through an object
• Note: C++ allows both object-oriented and procedural programming
5
C and C++ concepts
6
And no, I'm not a walking C++ dictionary. I do not keep every technical
detail in my head at all times. If I did that, I would be a much poorer
programmer. I do keep the main points straight in my head most of the
time, and I do know where to find the details when I need them.
Bjarne Stroustrup
7
Scope
• A scope is a region of program text
• Global scope (outside any language construct)
• Class scope (within a class)
• Local scope (between { … } braces)
• Statement scope (e.g. in a for-statement)
• A name in a scope can be seen from within its scope and within scopes nested within that
scope
• Only after the declaration of the name (“can’t look ahead” rule)
• Class members can be used within the class before they are declared
• A scope keeps “things” local
• Prevents my variables, functions, etc., from interfering with yours
• Remember: real programs have many thousands of entities
• Locality is good!
• Keep names as local as possible
[Link]/Programming 8
Scope
// no r, i, or v here
class My_vector {
vector<int> v; // v is in class scope
public:
int largest() // largest is in class scope
{
int r = 0; // r is local
for (int i = 0; i < [Link](); ++i) // i is in statement scope
r = max(r, abs(v[i]));
// no i here
return r;
}
// no r here
};
// no v here
[Link]/Programming 9
Namespaces
• Address the problem of naming conflicts between different parts of the code.
• Namespaces define the context (scope) in which names (types, functions, variables) are defined:
// namespace.h // [Link]
#include <iostream>
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
foo(); // equivalent to calling myscope::foo()
}
12
Pointers
• A pointer is an object whose value is the address in memory where another object is
stored
• A pointer to an object of type T is denoted by T*
• A null pointer does not refer to a valid address location; null pointer value provided by the
keyword nullptr
• Accessing the object to which a pointer refers is called dereferencing
• Dereferencing a pointer is done with the indirection operator *
• If p is a pointer, then *p is the object to which the pointer refers
• If x is an object of type T, then &x is the address of x (a pointer of type T*)
int a;
int* p = nullptr; // p is a pointer to an int
int* p1 = &a; // p1 is a pointer to an int (and points to the address of a)
13
References
• References are aliases (for an already existing object):
int var;
int& ref = var;
• From here on, ref is an alias for var. You cannot make ref an alias for another variable.
• References are not pointers.
• Note:
• Above are so-called lvalue references
• There is also the concept of rvalue references (used in the context of move constructors and
move assignment operators)
14
Parameter passing by reference
• Avoids (potentially expensive) copying
void swap(int& x, int& y) { // call swap() function
int tmp;
tmp = x; int a = 2;
x = y; int b = 3;
y = tmp;
} swap(a,b);
• Guarantee that a function does not modify parameters passed as const references
• Compiler-time check
15
Pointers vs. references
• Both can be used to refer to some other entity (e.g., an object or a function)
• Two key differences:
• References must refer to something; pointers can have null value (nullptr)
• References cannot be rebound; pointers can be modified to point to some other entity
• References have cleaner syntax; to be used, pointers must be dereferenced
• Pointers typically require memory management (new/delete)
• Prefer using references instead of pointers, unless:
• You need to refer to “nothing” (nullptr)
• You need to change what you refer to
16
Classes and objects
17
Classes
• A class is a user-defined type
• A class specifies:
• How objects of that type are represented (through its member variables)
• What operations can be performed on such objects (through its member functions)
• A class can have zero or more members:
• Data members (define the representation of objects of the class)
• Function members (define operations on objects of the class)
• Type members (define types associated with the class)
• The interface is the part of a class accessible to users
• The implementation of a class is the internal part of a class (accessible to users only
indirectly, through the class interface)
18
Class access specifiers
• Control the access level that users have to the class members
• There are three levels of access:
• public: these members can be accessed by any code
• protected: these members can be accessed by derived classes (related to inheritance)
• private: these members can only be accessed by other members of the class (also by friends of the
class)
19
Objects
• Classes are “first-class citizens”! They have the same standing as all built-in types
• Objects are variables of a certain class type (instances of that class)
• Objects can be passed to functions
• The return value of a function can be an object
• You can implement type-conversion operations to automatically convert objects from one
class to another
• All rules for resolving overloaded functions also apply to functions with object arguments
20
Example of a class
include guards
void SetDate(int year, int month, int day); Date::Date(int year, int month, int day)
void PrintDate() const; const function : m_year(year), m_month(month), m_day(day)
{
int GetYear() const {return m_year;} }
int GetMonth() const {return m_month;}
int GetDay() const {return m_day;} // Member functions
accessors void Date::SetDate(int year, int month, int day) {
implementation
#include “Date.h”
22
Constructors and destructors
• A constructor is a member function which initializes the class.
• A constructor has
• the same name as the class itself
• no return type
• A class can have more than one constructor, as long as the argument lists differ.
• A constructor is called automatically whenever a new instance of a class is created.
• You must supply the arguments to the constructor when a new instance is created.
• If no constructor is specified, the compiler generates a default constructor for you.
• may not be what you want!
23
Constructors and destructors
• A destructor is a member function which deletes an object.
• A destructor function is called automatically when the object goes out of scope:
1. the function ends
2. the program ends
3. a block containing temporary variables ends
4. a delete operator is called
• A destructor has:
• the same name as the class but is preceded by a tilde (~)
• no arguments and no return value
24
Constructors and destructors
/// Geometric object representing a piecewise cubic ChLineBezier::ChLineBezier(ChBezierCurve* path)
/// Bezier curve in 3D. : m_own_data(false), m_path(path) {
class ChApi ChLineBezier : public ChLine { complexityU = static_cast<int>(m_path->getNumPoints());
}
public:
ChLineBezier() : m_own_data(false), m_path(NULL) {} ChLineBezier::ChLineBezier(const std::string& filename) {
ChLineBezier(ChBezierCurve* path); m_path = ChBezierCurve::read(filename);
ChLineBezier(const std::string& filename); m_own_data = true;
ChLineBezier(const ChLineBezier& source); complexityU = static_cast<int>(m_path->getNumPoints());
ChLineBezier(const ChLineBezier* source); }
~ChLineBezier();
ChLineBezier::ChLineBezier(const ChLineBezier& source) : ChLine(source) {
// ... m_path = source.m_path;
// ... m_own_data = false;
complexityU = [Link];
private: }
bool m_own_data; ///< owns the data?
ChBezierCurve* m_path; ///< pointer to Bezier curve ChLineBezier::ChLineBezier(const ChLineBezier* source) : ChLine(*source) {
}; m_path = source->m_path;
m_own_data = false;
complexityU = source->complexityU;
}
ChLineBezier::~ChLineBezier() {
if (m_own_data)
delete m_path;
}
25
Smart pointers
26
C makes it easy to shoot yourself in the foot. C++ makes it harder, but
when you do, you blow away your whole leg!
Bjarne Stroustrup
27
Dynamic memory in C++
• Dynamic memory allocated using operator new
• new is followed by a data type specifier and, if needed, the number of elements (within [])
• new returns a pointer to the beginning of the new block of memory allocated
• new can use any variable value for size (since memory is assigned at run time)
• Dynamic memory no longer needed can be freed with the operator delete
• The value passed to delete must be a pointer previously allocated with new or nullptr
• delete releases memory of a single element allocated using new
• delete[] releases memory allocated for arrays of elements using new and size in brackets
29
Shared pointers
• Smart pointers are essential to the RAII programming idiom
• Smart pointers are class objects that behave like built-in pointers
• Smart pointers support pointer operations:
• dereferencing (operator *)
• member operator (operator ->)
• Smart pointers do additional things that regular pointers do not: automatic memory
management
// ...
delete p;
}
• This code will work fine (most of the time). What if somewhere in the function
DoSomething() an exception gets thrown?
• delete never gets called memory leak
• Use of a smart pointer solves this issue because the smart pointer will be cleaned up
whenever it gets out of scope (whether through normal execution or during an exception)
31
std::auto_ptr
• auto_ptr is a class template (available through the C++ Standard Library header
<memory>) that provides basic RAII features for C++ raw pointers
• The auto_ptr<T> template class describes an object that stores (wraps) a pointer to a
single allocated object of type T* and ensures that the object to which it points is
destroyed automatically when control leaves a scope
void foo() {
std::auto_ptr<myClass> p(new myClass);
p->DoSomething();
// ...
// delete p;
// p’s destructor called automatically as it goes out of scope
} 32
std::shared_ptr
• Introduced in C++11 (together with std::unique_ptr and std::weak_ptr)
• std::shared_ptr is a smart pointer; i.e., a C++ object with overloaded dereference and
indirection operators
• std::shared_ptr is a reference-counted object; i.e., it holds (wraps) a pointer to an object
and a pointer to a shared reference counter
• Every time a copy of the smart pointer is made, the reference counter is incremented
• When a shared pointer is destroyed, the reference counter is decremented
• When the counter reaches zero, the managed object (the wrapped raw pointer) is deleted
(its destructor is called)
33
std::shared_ptr
34
Prefer using std::make_shared
• When creating std::shared_ptr objects, prefer to use std::make_shared over explicitly
using new with shared_ptr
• More efficient
• Control block (reference count) and owned block (wrapped pointer) can be allocated
together
• One memory allocation instead of two (better cache efficiency)
• Better exception safety (avoids resource leaks)
35
std::weak_ptr & std::unique_ptr
• There are some situations where std::shared_ptr has problems (if the sharing graph has
cycles, the reference counter cannot reach zero)
• std::weak_ptr can be used to break such a cycle
• std::unique_ptr is a smart pointer that models unique ownership, meaning that at any
time in your program there shall be only one (owning) pointer to the pointed object
• std::unique_ptr is non-copyable
36
Inheritance and polymorphism
37
Inheritance
• Inheritance implements the “is a” relationship
• Example: Circle – Shape relationship
• Circle is “a kind of a” Shape
• Circle is “derived from” Shape
• Circle is “a specialized” Shape
• Circle is a “subclass” of Shape
• Circle is a “derived class” of Shape
• Shape is the “base class” of Circle
• Circle inherits properties and methods of Shape and adds its own behavior
• In C++, expressed through public inheritance:
39
Virtual functions
• Inheritance polymorphism depends on public virtual member functions
• Base class declares a member function virtual
• Derived classes override the base class definition of that function
animal->eat(); // outputs: "I'm eating generic food." animal->eat(); // outputs: "I'm eating generic food."
cat->eat(); // outputs: "I'm eating a rat." cat->eat(); // outputs: "I'm eating a rat."
42
The C++ Standard Template Library
• The C++ STL (Standard Template Library) is a powerful set of C++ template classes to
provides general-purpose templatized classes and functions that implement many popular
and commonly used algorithms and data structures like vectors, lists, queues, and stacks.
• Components
Containers Containers are used to manage collections of objects of a
certain kind. There are several different types of containers
like deque, list, vector, map etc.
Algorithms Algorithms act on containers. They provide the means by
which you will perform initialization, sorting, searching, and
transforming of the contents of containers.
Iterators Iterators are used to step through the elements of collections
of objects. These collections may be containers or subsets of
containers.
43
[Link]
#include <iostream>
#include <vector>
using namespace std;
int main() {
// create a vector to store int
vector<int> vec;
int i;
// display the original size of vec push_back() – inserts value at the end of the
cout << "vector size = " << [Link]() << endl;
vector, expanding its size as needed
// push 5 values into the vector
for (i = 0; i < 5; i++){
vec.push_back(i); size() – returns the size of the vector
}
45