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 fixes
C++03
• Smart pointers
• Regexes
• Hashmap and the likes
C++TR1
• We’ll learn today
C++11
• Minor language enhancements
C++14
Usability
List Initialization and Uniform
Initialization
struct MyStr
{
int i;
string s;
};
 Before
vector<MyStr> vec(2);
vec[0].i = 1;
vec[0].s = "1";
vec[1].i = 2;
vec[1].s = "2";
 After
MyStr myStr = { 1, "1" };
vector<MyStr> vec1 = {{ 1, "1" },{ 2, "2" }};
vector<MyStr> vec2{{ 1, "1" },{ 2, "2" }};
Support Uniform Initialization
struct Settings {
map<string, int> m;
Settings(
initializer_list<pair<string, int>> s) {
for (const auto& p : s)
{
m.insert(p);
}
}
};
Type Inference
std::map<std::string,
std::vector<std::string>> m = ...;
 Before
for(std::map<std::string,
std::vector<std::string>>::const_iterator
i = m.cbegin();
i != m.cend();
++i){ }
 After
for(auto i = m.cbegin(); i != m.cend(); ++i){}
auto Quiz
int 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 Loops
vector<MyStr> vec1 {{ 1, "1" },{ 2, "2" }};
 Before
for (size_t i = 0; i < vec.size(); ++i) {
const MyStr& s = vec[i];
// do something with s
}
 After
for (const auto& s : vec) {
// do something with s
}
More Range-Based Loops
map<string,vector<string>> m = ...;
 Before
for(map<string,
vector<string>>::iterator pi =
m.begin(); pi != m.end(); ++pi) {
pair<const string,
vector<string>>& pair = *pi;
}
 After
for (auto& pair : map) { }
Support Range-Based Loops
struct 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 Code
vector<MyStr> vec = ...;
 Before
struct MyStrComp {
bool operator()(const MyStr& s1,
const MyStr& s2) const {return s1.i>s2.i;}
};
sort(vec.begin(), vec.end(), MyStrComp());
 After
sort(vec.begin(), vec.end(),
[](const MyStr& s1, const MyStr& s2) {
return s1.i > s2.i;
});
Reference Capturing
vector<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
Before
class 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; }
};
After
class 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, &param1, 0, NULL),
CreateThread(NULL, 0, _StockThread, &param2, 0, NULL)
};
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
DeleteCriticalSection(&lock);
}
Standard Multi-Threading
mutex 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 Types
tuple<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!

What's New in C++ 11/14?

  • 1.
    What’s New in C++11? Dina Goldshtein she codes(jlm); July 2014
  • 2.
    Agenda  C++ History C++ 11  Usability  Standard library  C++ 14
  • 3.
    Some History • Firstreal standard • What is usually taught at universityC++98 • Bug fixes C++03 • Smart pointers • Regexes • Hashmap and the likes C++TR1 • We’ll learn today C++11 • Minor language enhancements C++14
  • 4.
  • 5.
    List Initialization andUniform Initialization struct MyStr { int i; string s; };  Before vector<MyStr> vec(2); vec[0].i = 1; vec[0].s = "1"; vec[1].i = 2; vec[1].s = "2";  After MyStr myStr = { 1, "1" }; vector<MyStr> vec1 = {{ 1, "1" },{ 2, "2" }}; vector<MyStr> vec2{{ 1, "1" },{ 2, "2" }};
  • 6.
    Support Uniform Initialization structSettings { map<string, int> m; Settings( initializer_list<pair<string, int>> s) { for (const auto& p : s) { m.insert(p); } } };
  • 7.
    Type Inference std::map<std::string, std::vector<std::string>> m= ...;  Before for(std::map<std::string, std::vector<std::string>>::const_iterator i = m.cbegin(); i != m.cend(); ++i){ }  After for(auto i = m.cbegin(); i != m.cend(); ++i){}
  • 8.
    auto Quiz int 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();
  • 9.
    Range-Based Loops vector<MyStr> vec1{{ 1, "1" },{ 2, "2" }};  Before for (size_t i = 0; i < vec.size(); ++i) { const MyStr& s = vec[i]; // do something with s }  After for (const auto& s : vec) { // do something with s }
  • 10.
    More Range-Based Loops map<string,vector<string>>m = ...;  Before for(map<string, vector<string>>::iterator pi = m.begin(); pi != m.end(); ++pi) { pair<const string, vector<string>>& pair = *pi; }  After for (auto& pair : map) { }
  • 11.
    Support Range-Based Loops structMyArr { 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]; } }
  • 12.
  • 13.
    Lambdas Shorten Code vector<MyStr>vec = ...;  Before struct MyStrComp { bool operator()(const MyStr& s1, const MyStr& s2) const {return s1.i>s2.i;} }; sort(vec.begin(), vec.end(), MyStrComp());  After sort(vec.begin(), vec.end(), [](const MyStr& s1, const MyStr& s2) { return s1.i > s2.i; });
  • 14.
    Reference Capturing vector<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 });
  • 15.
    Non-Static Data Initialization Before classComplex { 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; };
  • 16.
    Delegating Constructor Before class 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; } }; After class 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; };
  • 17.
  • 18.
    Upgrades to CurrentLibrary  Significant performance improvements when previously copying was required  Internal memory management  Return containers by value  Eliminate need to copy elements when inserting into containers
  • 19.
    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, &param1, 0, NULL), CreateThread(NULL, 0, _StockThread, &param2, 0, NULL) }; WaitForMultipleObjects(2, threads, TRUE, INFINITE); DeleteCriticalSection(&lock); }
  • 20.
    Standard Multi-Threading mutex 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();
  • 21.
    Tuple Types tuple<int, string,string> httpResponse = getPage("google.com"); string body = get<2>(httpResponse); int status; string header; tie(status, header, ignore) = getPage("yahoo.com");
  • 22.
    Smart Pointers  Noreason 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
  • 23.
    Unique Pointers  Passingby 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?
  • 24.
    Shared Pointers  Countsreferences 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);
  • 25.
    Weak Pointers  Sharedpointers 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 };
  • 26.
    Hash Tables  Betterperformance!  std::unordered_set  std::unordered_multiset  std::unordered_map  std::unordered_multimap
  • 27.
    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
  • 28.
    More Goodies inFuture 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
  • 29.
    More Stuff YouShould Know  Templates  STL algorithms  Rvalue references and move constructors  Variadic templates
  • 30.
    Summary  C++ History C++ 11  Usability  Standard library  C++ 14
  • 31.
  • 32.
    Exercise  Modernize somereal open-source code!  Download code from here: http://bit.ly/1ryNgji  Go crazy!

Editor's Notes

  • #9 auto i = getInt(); // int auto ir = getIntReference(); // int auto cir = getConstIntReference(); // int auto& i = getInt(); // doesn’t compile – can’t cast int to int& auto& ir = getIntReference(); //int & auto& cir = getConstIntReference(); //const int& - why? Because that’s the way it is const auto& i = getInt(); // const int& - but don’t do this! – it’s a temporary on the stack. If you pass I to other places you might have a problem! const auto& ir = getIntReference(); // const int& const auto& cir = getConstIntReference(); const int& מה המסקנה מכל זה? שימו את ה-& ואת ה-const בעצמכם איפה שצריך ולא יהיו בלבולים. זה לא מאריך את הקוד באופן משמעותי והקוד ברור!
  • #10 ואם אנחנו כבר מדברים על דרכים שבהן אפשר לקצר כתיבה של לולאות אז סוף סוף יש לנו סינטקס חדש ללולאות for – סינטקס שמאפשר לנו מעבר ישיר על איברים של container במקום שימוש באיטרטור ואז ב-dereference של האיטרטור הזה. בדוגמה הזאת קיצרנו קצת את הקוד.