int val = 42;
const int cval = 42;
Contact *c = new Contact;
std::vector<int> values = ...;
for (std::vector<int>::const_iterator it = values.cbegin(), end = values.cend();
it != end; it++) {
int val = *it;
std::cout << val << endl;
}
After
auto val = 42;
const auto cval = 42;
auto c = new Contact;
std::vector<int> values = ...;
for (auto it = values.cbegin(), end = values.cend();
it != values.cend(); it++) {
auto val = *it;
std::cout << val << endl;
}
Range for
Before
std::vector<int> values = ...;
for (std::vector<int>::const_iterator it = values.cbegin(), end = values.cend();
it != end; it++) {
int val = *it;
std::cout << val << endl;
}
After auto
std::vector<int> values = ...;
for (auto it = values.cbegin(), end = values.cend();
it != end; it++) {
auto val = *it;
std::cout << val << endl;
}
After
std::vector<int> values = ...;
for (auto val : values) {
std::cout << val << endl;
}
After (bis)
std::vector<int> values = ...;
for (auto &val : values) {
val = val * val;
}
Inherited constructors
Before
class Parent
{
public:
Parent(int i) : value(i) { /* do something */ }
protected:
int value;
};
class Child : public Parent
{
public:
Child(int i) : Parent(i), flag(false) {}
protected:
bool flag;
};
After
class Parent
{
public:
Parent(int i) : value(i) { /* do something */ }
protected:
int value;
};
class Child : public Parent
{
public:
using Parent::Parent;
protected:
bool flag = false;
};
Delegated Constructors
Before
class MyClass
{
public:
MyClass(int i, int j) { init(i, j); }
MyClass(int i, const char *j) { init(i, atoi(j)); }
private:
void init(int i, int j) { /* do something */ }
};
After
class MyClass
{
public:
MyClass(int i, int j) { /* do something */ }
MyClass(int i, const char *j) : MyClass(i, atoi(j)) {}
};
Uniform Initialization
Before
float array[] = { 0.0f, 1.42f, 42.3f };
int value = 7;
int other(8);
Circle c(Point(0, 0), 12);
std::vector<int> values;
values.push_back(1);
values.push_back(2);
After
float array[] = { 0.0f, 1.42f, 42.3f };
int value = {7};
int other{8};
Circle c1{ Point{0, 0}, 12 };
Circle c2{ {0, 0}, 12 };
std::vector<int> values{ 1, 2 };
Initializer Lists
#include <initializer_list>
class SharedMemList
{
public:
SharedMemList(std::initializer_list<int> l)
{
for (int param : l) {
storeInSharedMem(param);
}
}
...
};
class Parent
{
public:
virtual void method();
};
class Child : public Parent
{
public:
void method() override;
};
class Parent
{
public:
virtual void method(int value);
};
class Child : public Parent
{
public:
void method() override; // error!
};
final
class Parent
{
public:
virtual void method() final;
};
class Child : public Parent
{
public:
void method(); // error!
};
class Parent final
{
public:
virtual void method();
};
class Child : public Parent // error!
{
};
Smart Pointers
std::shared_ptr
using namespace std;
shared_ptr<Contact> c{new Contact(name, address)};
auto c = make_shared<Contact>(name, address);
// We assume `class Employee : public Contact`
// Ouch!
shared_ptr<Employee> e{ dynamic_cast<Employee>(c.get()) };
// Better!
auto e = dynamic_pointer_cast<Employee>(c);
// Assuming types Length and Area
constexpr Length operator "" _m(double m) {
return Length{m};
}
constexpr Length operator "" _cm(double cm) {
return Length{cm/100.0};
}
constexpr Area operator "" _sqm(double sqm) {
return Area{sqm};
}
...
// Assuming proper operators *, + and ==
// for Length and Area
auto area = 10.0_sqm + (2.0_m * 120.0_cm);
if (area == 12.5_sqm) {
...
}
Variadic Templates
int maximum(int n)
{
return n;
}
template<typename... Args>
int maximum(int n, Args... args)
{
return std::max(n, maximum(args...));
}
auto m = maximum(25, 42, 10, 30);
// m == 42
template<typename ... Types> class Tuple;
template<> class Tuple<> {};
template<typename Head, typename ... Tail>
class Tuple<Head, Tail...> {
Head m_head;
Tuple<Tail...> m_tail;
public:
Tuple(const Head &head, const Tail & ... tail)
: m_head(head), m_tail(tail...) {}
Head head() const { return m_head; }
Tuple<Tail...> tail() const { return m_tail; }
};
Multithread
std::thread
// Puts the result in some shared state
void computeFibonacci(int n);
std::thread t1{computeFibonacci, 42};
std::thread t2{
[]() { std::cout << 42 << endl; }
};
t1.join();
t2.join();
std::mutex
(and friends)
The usual locks…
std::future
+
std::async
unsigned long long fibonacci(unsigned n);
...
std::vector<std::future<unsigned long long>> results;
for (int n = 0; n < 45; n++) {
results.push_back(
std::async(launch::async, fibonacci, n)
);
}
for (auto &result : results) {
std::cout << result.get() << std::endl;
}