what's new in c++ 11/14?
DESCRIPTION
It's not your mother's C++ anymore. Manual memory management, tedious loops, difficult-to-use STL algorithms -- are all a thing of the past now. The new C++ 11 standard contains a huge number of improvements to the C++ core language and standard library, and can help C++ developers be more productive. In this session we will discuss the major features of C++ 11, including lambda functions, type inference for local variables, range-based for loops, smart pointers, and more. We will see how to use these features effectively to modernize your existing C++ programs and how to develop in the modern C++ style.TRANSCRIPT
What’s New in C++ 11?Dina Goldshtein
she codes(jlm);July 2014
Agenda C++ History
C++ 11 Usability Standard library
C++ 14
Some History•First real standard
•What is usually taught at universityC++98
•Bug fixesC++03•Smart pointers
•Regexes•Hashmap and the likes
C++TR1
•We’ll learn todayC++11
•Minor language enhancementsC++14
Usability
List Initialization and Uniform Initialization
struct MyStr{ int i; string s;};
Beforevector<MyStr> vec(2);vec[0].i = 1;vec[0].s = "1";vec[1].i = 2;vec[1].s = "2";
AfterMyStr myStr = { 1, "1" };vector<MyStr> vec1 = {{ 1, "1" },{ 2, "2" }};vector<MyStr> vec2{{ 1, "1" },{ 2, "2" }};
Support Uniform Initializationstruct Settings { map<string, int> m;
Settings( initializer_list<pair<string, int>> s) { for (const auto& p : s) { m.insert(p); } }};
Type Inferencestd::map<std::string, std::vector<std::string>> m = ...;
Beforefor(std::map<std::string, std::vector<std::string>>::const_iterator i = m.cbegin(); i != m.cend(); ++i){ }
Afterfor(auto i = m.cbegin(); i != m.cend(); ++i){}
auto Quizint getInt();int& getIntReference();const int& getConstIntReference();
auto i = getInt();auto ir = getIntReference();auto cir = getConstIntReference();
auto& i = getInt();auto& ir = getIntReference();auto& cir = getConstIntReference();
const auto& i = getInt();const auto& ir = getIntReference();const auto& cir = getConstIntReference();
Range-Based Loopsvector<MyStr> vec1 {{ 1, "1" },{ 2, "2" }};
Beforefor (size_t i = 0; i < vec.size(); ++i) { const MyStr& s = vec[i]; // do something with s} Afterfor (const auto& s : vec) { // do something with s}
More Range-Based Loopsmap<string,vector<string>> m = ...;
Beforefor(map<string, vector<string>>::iterator pi = m.begin(); pi != m.end(); ++pi) { pair<const string, vector<string>>& pair = *pi; }
Afterfor (auto& pair : map) { }
Support Range-Based Loopsstruct MyArr { int arr[100]; int size = 0; void push_back(int e) { arr[size++] = e; } int& operator[](int i) { return arr[i]; }};
namespace std { int* begin(MyArr& a){ return &a.arr[0]; } int* end(MyArr& a){ return &a.arr[a.size]; }}
Lambda Functions
][
Capture List
)(
Parameters
}{
Code
;)(
Invocation
Lambdas Shorten Codevector<MyStr> vec = ...;
Beforestruct MyStrComp { bool operator()(const MyStr& s1, const MyStr& s2) const {return s1.i>s2.i;}};sort(vec.begin(), vec.end(), MyStrComp()); Aftersort(vec.begin(), vec.end(), [](const MyStr& s1, const MyStr& s2) { return s1.i > s2.i;});
Reference Capturingvector<int> input{ 1, 2, 3, ... };vector<int> primes;for_each(input.cbegin(), input.cend(), [&primes](int n){ if (isPrime(n)) primes.push_back(n); });for_each(input.cbegin(), input.cend(), [=primes](int n){ if (isPrime(n)) primes.push_back(n); //doesn't compile });
Non-Static Data Initialization
Before
class Complex {public: Complex() { _x = _y = 0; } Complex(double x) :_x(x) { _y = 0; } Complex(double x, double y) : _x(x), _y(y) {}
private: double _x; double _y;};
After
class Complex {public:
Complex(double x) :_x(x) { }
Complex(double x, double y) : _x(x), _y(y) {}
private: double _x = 0; double _y = 0;};
Delegating Constructor
Beforeclass Complex {public: Complex() { init(); } Complex(double x) { init(); _x = x; } Complex(double x, double y) { init(); _x = x; _y = y; }private: double _x; double _y; void init() { _x = _y = 0; }};
Afterclass Complex {public: Complex() : Complex(0) { }
Complex(double x) : Complex(x, 0) { }
Complex(double x, double y) { _x = x; _y = y; }private: double _x; double _y;};
Standard Library
Upgrades to Current Library Significant performance improvements
when previously copying was required Internal memory management Return containers by value Eliminate need to copy elements when
inserting into containers
Oh man…struct _StockThreadParams { map<string, double>& stocks; string stockName; CRITICAL_SECTION* lock;};
DWORD WINAPI _StockThread(LPVOID p) { _StockThreadParams* param = (_StockThreadParams*)p; double stockValue = getStock(param->stockName); EnterCriticalSection(param->lock); param->stocks[param->stockName] = stockValue; LeaveCriticalSection(param->lock); return 0;}
void useOldThread() { CRITICAL_SECTION lock; InitializeCriticalSection(&lock); map<string, double> stocks; _StockThreadParams param1{ stocks, "apple", &lock }; _StockThreadParams param2{ stocks, "microsoft", &lock }; HANDLE threads[] = { CreateThread(NULL, 0, _StockThread, ¶m1, 0, NULL), CreateThread(NULL, 0, _StockThread, ¶m2, 0, NULL) }; WaitForMultipleObjects(2, threads, TRUE, INFINITE); DeleteCriticalSection(&lock);}
Standard Multi-Threadingmutex m;map<string, double> stocks;thread ta([&] { auto val = getStock("apple"); lock_guard<mutex> lg(m); stocks["apple"] = val;});thread tm([&]{ auto val = getStock("microsoft"); lock_guard<mutex> lg(m); stocks["microsoft"] = val;});ta.join(); tm.join();
Tuple Typestuple<int, string, string> httpResponse = getPage("google.com");string body = get<2>(httpResponse);
int status;string header;tie(status, header, ignore) = getPage("yahoo.com");
Smart Pointers No reason to use new or delete any
more... unique_ptr
Use when only a single reference is allowed at the same time
Passing a unique reference discredits the original one
shared_ptr Use when you want to share the instance
between multiple objects weak_ptr
Use to break up cycles
Unique Pointers Passing by value or returning from
function invalidates the previous reference
This is the most common case Any private member Factory methods
Why not simply use values instead?
Shared Pointers Counts references to find out when to
delete a raw pointer
struct employee {/*...*/};struct manager { vector<shared_ptr<employee>> employees;} bob;struct payroll_system { map<shared_ptr<employee>,double> salaries;} payroll;shared_ptr<employee> kate(new employee(/**/));payroll.salaries[kate] = 600000.0;bob.employees.push_back(kate);
Weak Pointers Shared pointers don’t solve the problem
of cyclic references
struct manager { std::vector<shared_ptr<employee>> employees;};struct employee { std::weak_ptr<manager> manager; void request_leave() { if (auto m = manager.lock()) { m->request_leave(*this); } } // m is shared_ptr<manager>, might be null};
Hash Tables Better performance!
std::unordered_set std::unordered_multiset std::unordered_map std::unordered_multimap
For the Mathematicians Random
distributions: uniform_int uniform_real bernoulli binomial geometric negative_binomial poisson exponential Gamma Weibull
extreme_value normal lognormal chi_squared cauchy fisher_f student_t discrete piecewise_constant piecewise_linear
More Goodies in Future C++14 Generic lambda functions auto lambda = [](auto x, auto y) { return x + y; }; Return-type inference auto foo(int i) { if (i == 1) return i; // return int else return foo(i - 1) + i; } STL enhancements:
Shared mutexes and locking Tuple addressing via type
More Stuff You Should Know Templates STL algorithms
Rvalue references and move constructors
Variadic templates
Summary C++ History
C++ 11 Usability Standard library
C++ 14
Questions?
Exercise Modernize some real open-source code!
Download code from here: http://bit.ly/1ryNgji
Go crazy!