maths and technologies for games modern c++ techniques c++11 and beyond co3303 week 21

34
Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Upload: frederick-palmer

Post on 03-Jan-2016

217 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Maths and Technologies for GamesModern C++ Techniques

C++11 and Beyond

CO3303

Week 21

Page 2: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Today’s LectureToday’s Lecture

1. C++ History and Standards

2. C++ Compilers and Standards

3. C++11 Feature Summary

4. Main C++11 Features

Page 3: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

C++ HistoryC++ History

• C++ originated as “C with classes” in 1979– Developed by Bjarne Stroustrup– Same intent as it has today, a high-performance language with

high-level features (initially classes, inheritance and strong typing)

• Renamed to “C++” in 1983• First commercial compiler and reference work in 1985

• C++ 2.0 in 1990– Multiple inheritance, static/const/protected members, templates,

exceptions and more

• Eventually standardised by the ISO in 1998 (C++98)

• The next major revision was C++11, in 2011

Page 4: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

C++ StandardsC++ Standards

• There have been four versions of the standard:• 1998: C++98

– The basis of most C++ code even today

• 2003: C++03– Addressed defects in the original standard text, no C++ changes

• 2011: C++11– A significant number of new features added. A major version.

• 2014: C++14– A few minor extensions and fixes to the features added in C++11

• 20??: C++17– Being worked on. So far not much content, but expected to grow.

Page 5: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

C++ CompilersC++ Compilers

• In practice, our code must target the flavour of C++ that our compiler supports, not the latest standards– Standards are only relevant if the major compilers support them

• Until recent years, Visual Studio has lagged behind in adopting standards– However, Microsoft has moved to a more rapid release cycle and

now all major compilers are adopting new features quickly

• Perhaps the four most significant compilers are:– MSVC (Visual Studio), GCC, Clang and Intel C++

• All now support the bulk of C++11– MSVC is still behind (constexpr support), but not too far– C++14 / 17 support is also rapidly becoming available

Page 6: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

“Modern” C++“Modern” C++

• With new C++ features now widely available, developers should begin to become familiar with them– C++ has in many ways become a “new” language

• Some new features are extremely powerful and their use potentially very complex– People are still discovering how this “new” C++ can be used– It certainly is more customisable than ever before. To truly

understand every detail requires even more expertise.

• Whilst many appreciate the developments, some argue against the increasing complexity of the language. – Yet C++ adheres to “you don’t pay for what you don’t use”, so this

complexity is not necessarily a problem.

Page 7: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

C++11 New Features SummaryC++11 New Features Summary

• Not an exhaustive list, but a summary of the essentials:– Types: auto, nullptr, new enums, new style functions, decltype– Simplified initialisation, member defaults– Range-based for loop– Parameters & return values: rvalues and move semantics– Constructor delegation and deletion, “final” virtual functions– Standard library: smart pointers, hash-tables, regex and much more– Lambda expressions: (anonymous functions, Javascript-like)– Constant expressions: code executed by the compiler– Template extensions such as variadic templates– Extensive support for multithreading

• For more details see:– Bjarne Stroustrup’s C++11 FAQ– Wikipedia’s C++11 feature list

Page 8: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Type-related FeaturesType-related Features

• auto, automatic type deduction:

auto i = 0; // a is intauto f = 0.0f; // f is a float

auto it = myVector.begin(); // “it” is the appropriate iterator

// Compare the above with the C++98 version:vector<MyClass>::iterator it = myVector.begin();

• decltype, type of a given expression:int a = 5;

float b = 12.5;decltype(a*b) r = a*b; // r is the type you get when you multiply

– auto would do the same, so is this useful? We will return to it…

Page 9: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Type-related FeaturesType-related Features

• nullptr, replacement for NULL or 0:

int* p = 0; // Pointer to nothing, C++98 styleint* p = nullptr; // C++11 version. Won’t be mixed up with int

• “Class” enumenum class Button // New optional word “class”{ Start, Stop, Pause };

Button FirstButton = Button::Start; // Must write Button::int Start = 0; // So this is not an error (would be in C++98)

• Typed enum, select the integer type you want to useenum Flag : char // Add the exact type you want to use after :{ Debug, NoWarnings, Strict };

Page 10: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Type-related FeaturesType-related Features

• New function style:

int Add(int a, int b) // Ordinary style (still available)auto Add(int a, int b) -> int // New style

• Why…?– Because this kind of thing is impossible in C++98:

// Multiply any two things togethertemplate<class T, class U>??? mul(T x, U y) { return x*y; } // What is the return type?

• Use new function style and decltypetemplate<class T, class U>auto mul(T x, U y) -> decltype(x*y) { return x*y; }

– Very useful for powerful template code

Page 11: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Uniform InitialisationUniform Initialisation

• Curly bracketed lists can be used to initialise most things

struct Point{ int x; int y; };Point A = {1,2};Point B{1,2}; // Same meaning, prefer {} instead of () in C++11Point* C = new Point{10,20};

void Draw( Point p ) {…}Draw({45,15});

#include <initializer_list> // Needed for STL {} initialiser supportint squares[4] = {1,4,9,16}; // Ordinary array, C++98 OKstd::list<int> grades = { 41, 56, 65, 51, 62, 78 }; // Now STL also

using namespace std; // Should use std::, but this slide is small!map<string, vector<string>> telephoneNumbers =

{ {"Bob", {"07985551234", "017725558879"} }, {"Ann", {"07955556321"} },};

Page 12: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Class Defaults and UsingClass Defaults and Using

• Can provide default values for class members– As an alternative to setting them in the constructor

class BankAccount{ public: BankAccount() {}

std::string mType = "Current"; float mBalance = 0.0f; float mOverdraft = -200.0f;

};

BankAccount account1; // All members set to defaults

• More readable version of typedef– Can make template definitions this way too

using IntIter = std::vector<int>::iterator;IntIter it = myVec.begin();

Page 13: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Range-based for LoopRange-based for Loop

• for loop over a container, C++98 style:

vector<int> scores;vector<int>::iterator it;for (it = scores.begin(); it != scores.end(); ++it) cout << *it;

• Range-based loop:vector<int> scores;for (value : scores) cout << value; // No iterator used at all, get value directly

• Works for anything that has begin() and end()– E.g. string, istream, STL containers, your own types etc.

for (auto x : {1,2,3,5,8}) // Using auto and initializer_list cout << x;

Page 14: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Constructor Delegation and DeletionConstructor Delegation and Deletion

• Constructors can call other constructors:

class Widget{ Widget(int area) {…} Widget(int width, int height) : Widget(width * height);}

• Constructors can be deleted or defaulted:

class Widget{ Widget() = default; // Make a default constructor Widget(Widget&) = delete; // Delete copy constructor, can’t make copies}

Page 15: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

“Final” virtual functions“Final” virtual functions

• Virtual functions can be specified as final, which means that inherited classes cannot override them

class IModel // Interface class{ virtual void Render();} class Model : public IModel // Inherited implementation class{ virtual void Render() final {…}; // Implement the interface function}

class SpecialModel : public Model // Further inheritance{ virtual void Render() {…}; // Error, can’t override final version}

–Make sure there is a good reason to do this.

Page 16: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

New Standard Library FeaturesNew Standard Library Features

• Many new features in the C++11 standard libraryFor example:– Hash maps: <unordered_set>, <unordered_map> etc.– Linked lists: <forward_list>

– Replacement for built-in array, <array>:std::array<int,5> numbers = {1,2,3,4,5};numbers[2] = 5;

– Arbitrary collection of different types, <tuple>std::tuple<int, string, float> things = {5, "Hello", 1.5f};cout << std::get<1>(things); // Outputs "Hello"

• tuple is an example of a new feature, variadic templates, that allows any number of template parameters.

• In this case it allows tuples to contain any number of types

Page 17: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

New Standard Library FeaturesNew Standard Library Features

• More examples:

–Generic function pointers <functional>:int multiply (int a, int b) { return a*b; }

std::function<int(int,int)> myFn = multiply;int r = multiply(5,6);

–Powerful (advanced) random number library <random>

–Timer libraries• <system_clock>, <monotonic_clock>, <high_resolution_clock>

–Regular expressions (complex string matching) <regex>

Page 18: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Smart PointersSmart Pointers

• Smart pointers are a new essential feature of the STL– Defined in the include file <memory>

– The C++98 approach:void Parse(File textFile, int size)

{ Dictionary* d = new Dictionary(size); d->read(); //... etc.

delete d; // If you forget this -> memory leak}

– Same operation in C++11:void Parse(File textFile , int size)

{ std::unique_ptr<Dictionary> d(new Dictionary(size)); d->read(); …} // Automatically deleted when it goes out of scope

Page 19: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Smart PointersSmart Pointers

• The syntax can be simplified:void Parse(File textFile, int size){ auto d = std::make_unique<Dictionary>(size); // "forwards" parameters to ctor d->read();

…} // d automatically deleted

–(strictly make_unique is C++14, it was left out of C++11 by accident!)

• unique_ptr is for objects that have a single “owner”–Copying unique_ptr transfers ownership, must use move semantics:

std::unique_ptr<int> a(new int); // Dynamically allocate int*a = 5;std::unique_ptr<int> b = std::move(a); // b points at the int, a is nullptr*b = 6;*a = 7; // error

Page 20: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Smart PointersSmart Pointers

• If have a class or function that needs access to the contents of your pointer, but you don’t want to transfer ownership, then just use a “raw” pointer:bool Validate(const Dictionary* d) {…} // Want to use the dictionary, not own it

std::unique_ptr<Dictionary> d(new Dictionary(size)); if (!Validate( d.get() )) // get() function gives you a raw pointer{…}

–It is the programmer’s responsibility to check object lifetimes in their program in cases like this.

• If the unique pointer is destroyed, the raw pointer will be invalid.

–However, cases like the one illustrated above are common. One object will own the unique_ptr, other objects and functions will use it through raw pointers.–Aim to have all your classes use unique_ptrs for ownership. You should almost never need to write new and delete again!

Page 21: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Smart PointersSmart Pointers

• Sometimes, multiple objects share a pointer, and the object should only be deleted when all the owners are deleted.– E.g. the mesh of a game object that has many entities using it. Only

destroy the mesh when all the entities have gone.

• In such cases, you might use shared_ptr – Has an internal reference count to decide when to delete itself– Basic usage is the same as unique_ptr (use make_shared)– (Note: there is a helper weak_ptr to avoid cycles of shared_ptrs)

• When passing / returning shared_ptr you have a choice:– By value, internal count is increased– By reference, internal count is not increased

• However, shared_ptr should be used rarely– In the above case, a mesh manager could hold a unique_ptr instead

Page 22: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Lambda ExpressionsLambda Expressions

• Lambda expressions are functions declared “inline”// Some 2D pointsstruct Point {int x; int y;};std::vector<Point> pts = {{5,1}, {1,2}, {3,7}, {10,-1}};

// Sort function, pass vector of points and a less-than function for the sortingvoid Sort(std::vector<Point>& data, std::function<bool(Point,Point)> lessThan){ if (!lessThan(data[0], data[1])) std::swap(data[0], data[1]); //...}

// Using the Sort function with lambdas// [] starts the lambda, then the parameter list, then the function code// These lambda functions are passed to the 2nd parameter of Sort aboveSort(pts, [](Point a, Point b){ return a.x < b.x; }); // Sort points on x value

Sort(pts, [](Point a, Point b){ return a.y < b.y; }); // Sort points on y value

// Sort points on Manhattan distance from originSort(pts, [](Point a, Point b){ return a.x + a.y < b.x + b.y; });

Page 23: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Lambda ExpressionsLambda Expressions

• Lambdas can “capture” variables from the outer scope– Very useful feature, but be clear how it works:

auto x = 5; // Variables must be in scope when we declare lambdas using them

// Store the lambdas in variables in this exampleauto inc_x = [&](){ x++; }; // Increase (by reference) variable called xinc_x(); auto x_plus_5 = [=](){ return x+5; }; // Return 5 + copy of x taken on

this lineinc_x();cout << x << x_plus_5(); // outputs 7, 11 (because x_plus_5 captured x at 6)

• The capture is specified in the [][] Capture nothing[&] Capture any variables by reference[=] Capture any variable by making a copy[=, &v] Capture any variable by copy, but v by reference[this] Capture the this pointer of the enclosing class

Page 24: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Lambda ExpressionsLambda Expressions

• Lambdas are very useful with STL <algorithm> functions– Similar code style to several Javascript libraries

// Output container of integersstd::for_each(v.begin(), v.end(), [] (int i)

{ cout << i;});

// Remove odd numbers from containerstd::remove_if(v.begin(), v.end(), [] (int i){ return ((i%2)==1);});

// Find first rectangle in container with area > 100auto x = std::find_if(v.begin(), v.end(), [] (Rect r)

{ return r.w * r.h > 100;});

Page 25: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Constant ExpressionsConstant Expressions

• Functions that are declared constexpr will be evaluated by the compiler where possible:

constexpr int multiply(int x, int y) { return x * y; }

const int val1 = multiply(10, 10); // Function is executed by compiler

int a, b;cin >> a >> b;int val2 = multiply(a, b); // Function is executed at runtime

–There are many limitations on the kinds of functions that can be executed at compile time.

• In particular they must be only a single return statement

• Use constexpr for compile-time tests or to replace macros:constexpr int GetDefaultArraySize(int multiplier) { return 10 * multiplier; }int myArray[ GetDefaultArraySize(3) ];

Page 26: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Constant ExpressionsConstant Expressions

• Simple objects can also be constructed using constexprclass Circle{public: constexpr Circle (int x, int y, int radius) : mX(x), mY(y), mRadius(radius) {} constexpr double getArea() { return mRadius * mRadius * 3.1415926; }private: int mX; int mY; int mRadius;};

constexpr Circle c( 0, 0, 10 ); // Object constructed by compilerconstexpr double area = c.getArea(); // Area calculated by compiler

Pixel circlePixels[int(area)]; // Fixed size array based on calculation

Page 27: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Multithreading SupportMultithreading Support

• Threading support is provided in the standard library– Simple example:

#include <thread>

void threadStart(){ // Do something in first thread}

int main(){ std::thread t1(threadStart); // Start first thread at given function

std::thread t2([](){ cout << "I am a thread"; }); // Lambda second thread

// Do something in main thread

t1.detatch(); // Let 1st thread run on its own (don’t wait for it) t2.join(); // Wait for the second thread to finish

}

Page 28: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Multithreading SupportMultithreading Support

• Full range of locking features is availablestd::mutex funcLock; void func(){ funcLock.lock();

// Do something that needs synchronisation

funcLock.unlock(); // Also std::lock_guard, which auto-unlocks on destruction} std::thread t1(func);std::thread t2(func);

// Threads t1 and t2 cannot run the func code at the same time due to the mutex

t1.join();t2.join();

Page 29: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Rvalue ReferencesRvalue References

• Broadly speaking, an rvalue is an expression that is used temporarily and does not persist onto the next line.

int square(int x) { return x*x; }int a = square(12); // square(12) is an rvalue, 12 is also an rvalue

• For example, you cannot assign into rvalues12 = a; // Error square(12) = 143; // Error

• In C++98, rvalue references are not allowed

void increment(int& x) { x++; } // Reference parameterint a = 5;increment(a); // OK, a becomes 6increment(3); // Error, incrementing a literal value???increment(square(12)); // Error, incrementing the return value???

Page 30: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Rvalue ReferencesRvalue References

• In C++11, rvalue references are supported

void increment(int&& x) { x++; } // Two &’s for an rvalue referenceincrement(3); // Makes temp variable that is increased (then discarded)increment(square(12)); // Same, makes a temporary variable

–Of course this is useless and not the intent. This is just an illustration that rvalue references capture temporary values.

• However constructing objects with rvalues is very useful

class BigThing{ // “Move” constructor. “x” is a rvalue reference so we know that it is a // temporary variable and we can steal its resources, no need to copy anything BigThing( BigThing&& x ); };

–This “move” constructor can save on copies where temporaries occur–So when is this useful? Very often it turns out…

Page 31: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Rvalue ReferencesRvalue References

• Consider this typical operation in C++98:

template<class T> swap(T& a, T& b){ T temp(a); // Makes a complete copy of a (copy constructor) a = b; // Copies entire content of b to a (assignment) b = temp; // Copies entire content of tmp to b}

–Three copy operations are needed, possibly expensive–But no new data was actually needed…

• Same operation in C++11 (shown in detail on the next slide):

template<class T> swap(T& a, T& b){ T temp(std::move(a)); // std::move converts “a” into a temporary… a = std::move(b); // If the type T has a move constructor… b = std::move(temp); // …then no copying occurs at all}

Page 32: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Rvalue referencesRvalue references

• In more detail…

template<class T> swap(T& a, T& b){a is converted to a temporary, which means it doesn’t need to keep its data. So the type T can have a move constructor that simply steals the data of a. For example, if a contains an array of 1000 integers, the new variable temp just points at that array as its own, knowing that a doesn’t need it anymore. No copy needed. T temp(std::move(a));

a still exists as a variable though, and now we assign it to b. This time a move assignment operator is used: same idea: a just steals b’s data.a = std::move(b);

Same again, b steals the data back from temp. Process complete and no copying occurred at all. b = std::move(temp); }

–This process requires us to write move constructors and move assignment operators. They must intelligently copy pointers, and not the actual data (in fact, this is a deliberate shallow copy).

Page 33: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

Rvalue References UsageRvalue References Usage

• Rvalue references remove unnecessary copying

• The STL contains move constructors and move assignment operators wherever possible.– Algorithms within the STL use “move semantics” if they can– For example vector::push_back can take an rvalue parameter, so myVector.push_back(BigThing()); will not copy the BigThing, it will construct directly into the vector

• That means that many of the benefits of rvalue references come simply by using the STL– Write move constructors & assignments for expensive-to-construct

objects that you expect to pass around– One by-product is that passing or returning by value is no longer

inefficient if you are using classes that use move semantics

Page 34: Maths and Technologies for Games Modern C++ Techniques C++11 and Beyond CO3303 Week 21

FinallyFinally

• Presented the basics of most C++11 new features– Too much to cover in one lecture, so do explore the earlier links

• Support for these features is here now, so start using them!

• Quick list of interesting topics not covered:– Variadic templates, <type_traits>

• Template programming is now incredibly powerful.• Can effectively be used to extend the language.

– Research “Tempate Metaprogramming”

• Guru level difficulty. Use sparingly for core libraries only.

– Alignment of variables: alignof, alignas– static_assert. User-errors at compile time, good with constexpr

– New literal types, e.g. Unicode literals, user-defined literal styles– long long int type, guaranteed to be 64-bit