CS 1666 www.cs.pitt.edu/~nlf4/cs1666/ Programming in C++ First, - - PowerPoint PPT Presentation

cs 1666
SMART_READER_LITE
LIVE PREVIEW

CS 1666 www.cs.pitt.edu/~nlf4/cs1666/ Programming in C++ First, - - PowerPoint PPT Presentation

CS 1666 www.cs.pitt.edu/~nlf4/cs1666/ Programming in C++ First, some praise for C++ "It certainly has its good points. But by and large I think its a bad language. It does a lot of things half well and its just a garbage heap


slide-1
SLIDE 1

CS 1666

www.cs.pitt.edu/~nlf4/cs1666/

Programming in C++

slide-2
SLIDE 2
  • "It certainly has its good points. But by and large I think it’s a bad
  • language. It does a lot of things half well and it’s just a garbage

heap of ideas that are mutually exclusive." ○ Ken Thompson, designer and implementer of Unix

  • "It would make him physically ill to think of programming in C++"

○ Donald Knuth, referring to Edsgar Dijkstra

  • "Within C++, there is a much smaller and cleaner language

struggling to get out" ○ Bjarne Stroustrup ■ Creator of C++

First, some praise for C++

2

slide-3
SLIDE 3
  • Be a better C

○ Continue to provide low-level performance control ○ Stronger typechecking ○ Not entirely backwards compatible ○ "As Close as Possible to C, but no Closer"

  • Support data abstraction
  • Support object-oriented programming
  • Support generic programming

Goals for C++

3

slide-4
SLIDE 4

C Family Tree by Bjarne Stroustrup

4

slide-5
SLIDE 5
  • Initial work on "C with classes" started in 1979

○ Precursor to C++

  • Renamed to C++ in 1983
  • C++ 2.0 released in 1989
  • First C++ standard published by ISO in 1998

○ C++98

  • More recent standards:

○ C++03 ○ C++11 ○ C++14 ○ C++17

C++ history

5

slide-6
SLIDE 6

C++ history in this course

6

slide-7
SLIDE 7

Re: C++ history in this course

7

slide-8
SLIDE 8

When you code something that will definitely break your computer:

With great power comes great responsibility

8

Rust: C++:

slide-9
SLIDE 9

#include <iostream> int main() { std::cout << "Hello, World!\n"; }

Hello world

9

slide-10
SLIDE 10
  • ::
  • Has a few use cases, e.g.:

○ Accessing global variables ■ int x = 0; int main() { int x = 0; x = 1; ::x = 2; }

The scope resolution operator

10

slide-11
SLIDE 11
  • To define class methods outside of the class
  • To access static class attributes
  • To sort out ambiguities in multiple inheritance
  • Accessing members of scoped enums
  • To access identifiers defined within a namespace

Other scope resolution operator uses

11

slide-12
SLIDE 12
  • namespace A {

int x = 7; } namespace B { int x = 8; } int x = 0; int main() { int x = 0; x = 1; ::x = 2; A::x = 3; B::x = 4; }

Namespaces

12

slide-13
SLIDE 13

#include <iostream> int main() { using namespace std; cout << "Hello, World!\n"; }

Hello world (again)

13

slide-14
SLIDE 14
  • Streams convert typed objects to/from a stream of

characters (bytes)

  • std::cout is the standard output stream (STDOUT)
  • << is the output (or "put to") operator

○ Overloaded to operate on a stream and different types ○ Returns a reference to the stream that was output to

cout << 1 << "b" << var5;

Streams

14

slide-15
SLIDE 15
  • cin is the standard input stream (STDIN)
  • >> is the input (or "get from") operator

○ Again returns a reference to the original stream to allow for chaining ○ Type of right hand side determines type of value being read ○ Generally considers and whitespace to be a delimiter ■ To read a line with whitespace, use std::getline() ○ Will stop reading a number when first non-numeric character is encountered.

Input streams

15

slide-16
SLIDE 16

#include <iostream> using std::cout; using std::endl; int main() { cout << "Hello, World!" << endl; }

Hello world (one more time)

16

slide-17
SLIDE 17
  • Most of the C types you know and love are available:

○ E.g., char, bool, short, int, long, signed, unsigned, float, double, void, etc.

  • Has additional syntax for initialization via initializer lists

○ double d1 = 0.1; ○ double d2 {2.3}; ○ int i1 = 4.5; ○ int i2 {6.7};

  • Can use auto type when type is clear from initialization:

○ auto d3 = 8.9; ○ auto i3 {10};

Variable declarations

17

slide-18
SLIDE 18

+

  • *

/ % ++

  • +=
  • =

*= /= %=

Operators

18

== != < <= > >= && || ! & | ^ ~

slide-19
SLIDE 19
  • Local
  • Global
  • Class
  • Namespace

Scope

19

slide-20
SLIDE 20
  • const

○ "I promise not to change this value" ○ const int ans = 42;

  • constexpr

○ Must be evaluated at compile time ○ constexpr int ans = 42; ○ constexpr int res = sum(x, y); ■ Error, cannot be evaluated at compile time

Constants

20

slide-21
SLIDE 21
  • int x;
  • int* y;
  • int& z;

○ Error

  • int& z = x;
  • &x
  • *y

Pointer review

21

slide-22
SLIDE 22
  • In addition to C-style for loops, C++ offers a range for

statement

○ for (auto x : arr) cout << x << endl; ■ Copies each item in array arr into x and executes loop body ○ for (auto& x : arr) cout << x << endl; ■ Creates a reference to each array element and executes loop body

Range for statement

22

slide-23
SLIDE 23
  • What is the difference between NULL, 0, and '\0'?
  • C++ improves these easily confused points with the

introduction of nullptr

  • nullptr is a standin for the null pointer

○ There is only one, shared by all pointer types ○ Cannot be converted to an int ○ Can be converted to a bool ■ Given int* p:

  • if(*p) is the same as if(*p != 0)
  • if(p) is the same as if(p != nullptr)

NULL

23

slide-24
SLIDE 24

class Rectangle { public: Rectangle(int l, int w) :length{l}, width{w} {} void printArea() { std::cout << area() << std::endl; } private: int length, width; int area() { return length * width; } };

OOP

24

slide-25
SLIDE 25

class Square { public: Square(int s); void printArea(); private: int side; int area(); }; Square::Square(int s) { side = s; } void Square::printArea() { std::cout << area() << std::endl; } int Square::area() { return side * side; }

OOP2

25

slide-26
SLIDE 26
  • Compiler will try to generate code at each point of call

instead of using function call instruction

○ Can save on function call overhead!

  • Use the inline keyword before return type in function

declaration

○ Or define a method within the class definition ■ E.g., like we did in Rectangle ■ Can still use inline keyword on methods not defined in class definition

  • Note that compiler may not be able to abide by the request

to inline

Inline functions

26

slide-27
SLIDE 27

Rectangle r(5, 2); Square* s = new Square(4); r.printArea(); s->printArea();

  • > vs .

27

slide-28
SLIDE 28

class MyArray { public: MyArray(int s) :arr{new int[s]}, sz{s} {} int& operator[](int i){ return arr[i]; } int size() { return sz; } private: int* arr; int sz; };

Consider the following:

28

slide-29
SLIDE 29
  • A default constructor

○ MyArray() :arr{nullptr}, sz{0} {} ■ Note this should be invoked as MyArray a;

  • What's wrong with MyArray a();?
  • A destructor

○ ~MyArray() { delete[] arr; } ○ Cleans up memory allocated via new in constructor

Things to add

29

slide-30
SLIDE 30
  • Consider the following:

○ MyArray m(10); for (auto i=0; i<10; i++) { m[i] = i; } MyArray n = m; MyArray o;

  • = m;

n.sz = 20; n[2] = 20;

  • .sz = 30;
  • [3] = 30;

Copying classes

30

slide-31
SLIDE 31
  • If your class needs any one of these, it probably needs all 5:

○ Destructor ○ Copy constructor ○ Move constructor ○ Copy assignment operator ○ Move assignment operator

Rule of 5

31

slide-32
SLIDE 32

MyArray(const MyArray& a) :arr{new int[a.sz]}, sz{a.sz} { for (int i=0; i<sz; i++) arr[i] = a.arr[i]; }

Copy constructor

32

slide-33
SLIDE 33

MyArray& operator=(const MyArray& a) { int* p = new int[a.sz]; for (int i=0; i<a.sz; i++) p[i] = a.arr[i]; delete[] arr; arr = p; sz = a.sz; return *this; }

Copy assignment operator

33

slide-34
SLIDE 34
  • type&& creates an rvalue reference
  • E.g.:

○ int x = 10; ○ int& r = x; ■ OK ○ int&& rr = x; ■ Error, x is an lvalue ○ int& r2 = x + 5; ■ Error, x + 5 is an rvalue ○ int&& rr2 = x + 5; ■ OK

rvalues and lvalues

34

slide-35
SLIDE 35
  • A class Test that overloads operator+()
  • Assume we have valid x and y Test objects
  • Test t;

t = x + y;

  • We create new Test object as the result of x + y

○ But it's an rvalue

  • Assignment operator will perform a copy of x + y object
  • And then the rvalue x + y object will be destroyed!
  • Better to move instead of copy and destroy

Consider the following:

35

slide-36
SLIDE 36

MyArray(MyArray&& a) :arr{a.arr}, sz{a.sz} { a.arr = nullptr; a.sz = 0; }

Move constructor

36

slide-37
SLIDE 37

MyArray& operator=(MyArray&& a) { if (this != &a) { arr = a.arr; sz = a.sz; a.arr = nullptr; a.sz = 0; } return *this; }

Move assignment operator

37

slide-38
SLIDE 38
  • Should be familiar from Java:

○ template <typename T> int compare(const T& v1, const T& v2) { if (v1 < v2) return -1; if (v2 < v1) return 1; return 0; }

Templates

38

slide-39
SLIDE 39

template<typename T> class MyArray { private: T* arr; int sz; public: // … T& operator[](int i); // … };

Class template

39

slide-40
SLIDE 40
  • Functions that are declared, but not defined

○ Prefix the function declaration with virtual

  • Pure virtual must be implemented by a derived class

○ Suffix the function declaration with =0 ○ Any class with unimplemented pure virtual functions is considered an abstract class and cannot be instantiated.

  • Abstract classes can be used to create interfaces

○ No interface keyword like in Java ○ Just a class with unimplemented pure virtual functions ○ Can implement multiple interfaces due to support for multiple inheritance

Virtual functions

40

slide-41
SLIDE 41

class Container { public: virtual int& operator[](int) = 0; virtual int size() = 0; virtual ~Container() {} };

An abstract container class

41

slide-42
SLIDE 42

class MyArr_container : public Container { public: MyArr_container(int s) : m(s) { } ~MyArr_container() {} int& operator[](int i) override { return m[i]; } int size() override { return m.size(); } private: MyArray m; };

Inheritance

42

slide-43
SLIDE 43
  • Anonymous functions
  • E.g., [] (int x) { return x * x; }
  • If no arguments passed, in argument list can be omitted

○ Hence minimal lambda expression is [] { }

  • Return type inferred from simple lambda expressions

○ void if no return statement ○ If body is only a single return statement, return type is the type of that return's expression ○ Otherwise, return type must be specified ■

[] (bool x) { if x return 1; else return 2; }

  • Error, too complicated

[] (bool x)->int { if x return 1; else return 2; }

Lambda expressions

43

slide-44
SLIDE 44
  • What if you want to reference a variable from the containing

scope within a lambda expression?

  • [] allows you to express how such values can be captured

○ [] ■ No local names used in lambda body ○ [&] ■ All local names available by reference ○ [=] ■ All local names available by value ○ [x,&y,&z] ■ x available by value, y and z available by reference ○ [&,x] ■ All available by reference except for x available by value ○ [=,&y,&z] ■ All available by value except for y and z available by reference

Capture

44

slide-45
SLIDE 45
  • #include <string>
  • Generally what you should use to represent strings in C++
  • ver char*'s you're used to from C

std::string

45

slide-46
SLIDE 46
  • #include <vector>
  • Unless you have a good and specific reason for using an

array, you'll probably want to use a vector as your general container type in C++

std::vector

46

slide-47
SLIDE 47
  • An iterator points to some element in a range of elements

and cat to iterate through the elements of that range ○

Implements at least:

Increment operator ++

Dereference operator *

  • std::vector::begin() returns an iterator pointing to the

first element in the vector

  • std::vector::end() returns an iterator pointing to the last

element in the vector

Iterators

47

slide-48
SLIDE 48
  • RAII
  • =default and =delete member functions
  • const member functions
  • std::unique_ptr and std::shared_ptr
  • std::regex
  • Variadic Templates
  • Compile-Time if
  • … and much more

Not covered (but good to know)

48