SlideShare a Scribd company logo
1 of 53
Download to read offline
1
2
карты
Rvalue references
in C++11
Дмитрий Прокопцев
Яндекс.Карты, старший разработчик
3
Кто мы такие
Пишем на С++11 с 2010 года;
Продирались через черновики стандарта;
Набили шишек и получили опыт :)
4
Краткое содержание
!  Зачем всё это нужно?
!  Новые ссылки в языке
!  Перемещение классов
!  Как быть с исключениями
!  Универсальные ссылки
5
Зачем?
!  Скорость работы:
–  std::vector<X> v = vector_with_400M_items();
!  Семантическая ясность:
–  std::unique_ptr<X> make_x();
–  std::thread spawn_thread();
–  std::iostream tcp_connect(const std::string& addr);
6
Но ведь уже было?
template<class T> class auto_ptr {
private:
T* held;
public:
// needed for ‘auto_ptr<X> y2 = y1’
auto_ptr(auto_ptr<X>& other) {
held = other.held;
other.held = 0;
}
// see next page...
};
7
Но ведь уже было?
template<class T> class auto_ptr { // cont’d
public:
// needed for ‘auto_ptr<X> x = f()’
struct auto_ptr_ref {
auto_ptr<T>* ptr;
auto_ptr_ref(auto_ptr<T>* self): ptr(self) {}
};
operator auto_ptr_ref() { return auto_ptr_ref(this); }
auto_ptr(auto_ptr_ref ref) {
held = ref.ptr->held;
ref.ptr->held = 0;
}
};
8
Но ведь уже было?
!  Одни и те же 10 строк для каждого класса;
!  Семантическая неоднозначность:
–  std::vector<char> v2 = v1; // копирование
–  std::auto_ptr<X> p2 = p1; // перемещение
–  template<class X> void f(X& x) {
X y = x; // копирование? перемещение?
}
9
Ревизия ссылок
! T::T(const T&)
–  Копирование;
–  Может быть вызвано и от lvalues, и от временных объектов;
! T::T(T&)
–  Подразумеваемое перемещение (по стандарту -- копирование);
–  Ссылка связывается только с lvalues,
не позволяет перемещать из временных объектов.
! T::T(T_ref)
–  Подразумеваемое перемещение;
–  T_ref «связывается» и с lvalues, и с rvalues;
10
Новый вид ссылок:
T&&
11
Что к чему приводится
F(X&)	
   F(const	
  X&)	
   F(X&&)	
  
x	
  
xlref	
  
fxlref()	
  
Да	
   Если	
  нужно	
   sta6c_cast	
  
xclref	
  
fxclref()	
  
Нет	
   Да	
   Нет	
  
fx()	
  
fxrref()	
  
Нет	
   Если	
  нужно	
   Да	
  
xrref	
   Да	
   Если	
  нужно	
   sta6c_cast	
  
X	
  x;	
  
X&	
  xlref	
  =	
  /*...*/;	
  
const	
  X&	
  xclref	
  =	
  /*...*/;	
  
X&&	
  xrref	
  =	
  /*...*/;	
  
X	
  fx();	
  
X&	
  fxlref();	
  
const	
  X&	
  fxclref();	
  
X&&	
  xrref();	
  
12
Что к чему приводится
F(X&)	
   F(const	
  X&)	
   F(X&&)	
  
x	
  
xlref	
  
fxlref()	
  
Да	
   Да	
   sta6c_cast	
  
xclref	
  
fxclref()	
  
Нет	
   Да	
   Нет	
  
fx()	
  
fxrref()	
  
Нет	
   Если	
  нужно	
   Да	
  
xrref	
   Да	
   Да	
   sta6c_cast	
  
X	
  x;	
  
X&	
  xlref	
  =	
  /*...*/;	
  
const	
  X&	
  xclref	
  =	
  /*...*/;	
  
X&&	
  xrref	
  =	
  /*...*/;	
  
X	
  fx();	
  
X&	
  fxlref();	
  
const	
  X&	
  fxclref();	
  
X&&	
  xrref();	
  
13
Можно грабить корованы классы
template<class T>
bool has_duplicates(const std::vector<T>& v) {
// make a copy and play with it
std::vector<T> tmp = v;
std::sort(tmp.begin(), tmp.end());
return std::unique(tmp.begin(), tmp.end()) != tmp.end();
}
template<class T>
bool has_duplicates(std::vector<T>&& v) {
// ‘v’ points to a temporary; no need to make a copy
std::sort(v.begin(), v.end());
return std::unique(v.begin(), v.end()) != v.end();
}
14
Перемещение
классов
15
Перемещающие операции
! T::T(const T&);
–  копирующий конструктор;
! T& T::operator = (const T&);
–  копирующее присваивание;
! T(T&&);
–  перемещающий конструктор;
! T& T::operator = (T&&);
–  перемещающее присваивание.
16
Пример: std::vector
template<class T> class vector { // not really
private:
T *start, *finish, *storage_end;
public:
vector(const vector<T>&); // omitted
vector& operator = (const vector<T>&); // omitted
vector(vector<T>&& v):
start(v.start), finish(v.finish),
storage_end(v.storage_end)
{ v.start = v.finish = v.storage_end = 0; }
vector<T>& operator = (vector<T>&& v) {
std::swap(start, v.start);
std::swap(finish, v.finish);
std::swap(storage_end, v.storage_end);
}
};
17
Время жизни объекта, из которого
выполнили перемещение,
не заканчивается!
18
Вспоминаем Майерса
«Если вашему классу нужен пользовательский
конструктор копирования, оператор копирующего
присваивания, конструктор перемещения, оператор
перемещающего присваивания или деструктор -- скорее
всего, ему нужно всё вышеперечисленное.»
19
Делать ли класс перемещаемым?
!  Перемещающее присваивание можно сделать всегда;
–  достаточно обменять все поля класса;
!  Перемещающий конструктор требует наличия пустого
состояния;
–  оно моделируется пустым конструктором;
!  Перемещающее присваивание без перемещающего
конструктора выглядит странно;
!  Если у класса нет допустимого пустого состояния –- проще
целиком запретить перемещение.
20
Базис класса
!  Класс перемещаемый
–  T::T();
–  T::T(const T&);
–  T& T::operator = (T&&);
–  T::T(T&& t): T()
{ *this = static_cast<T&&>(t); }
–  T& T::operator = (const T&)
{ return *this = T(t); }
!  Класс неперемещаемый:
–  T::T(const T&);
–  void T::swap(T&);
–  T& T::operator = (const T&) {
T(t).swap(*this);
return *this;
}
21
Автогенерация методов
!  Если у класса нет недефолтных копирующих методов или
деструктора -- компилятор сгенерирует перемещающие
методы сам;
!  Если у класса есть пользовательские перемещающие
методы -- копирующие методы генерироваться не будут.
!  Всегда можно попросить компилятор сгенерировать метод:
–  T(T&&) = default;
–  T& operator = (T&&) = default;
22
Заботливо разложенные грабли
class screen { // came from year 2004
private:
std::vector< std::vector<char> > chars;
public:
screen(): chars(25, std::vector<char>(80, ‘x20’)) {}
void put_char(int x, int y, char c) {
chars[y][x] = c;
}
};
23
Если	
  у	
  класса	
  есть	
  инвариант,	
  
не	
  являющийся	
  следствием	
  инвариантов	
  всех	
  его	
  
полей	
  и	
  баз	
  –	
  
перемещение	
  классу	
  нужно	
  писать	
  руками!	
  
24
Перемещение из переменных
void f(const X&); // #1
void f(X&&); // #2
void g() {
X x;
f(x); // uses #1
f(static_cast<X&&>(x)); // uses #2
f(std::move(x)); // uses #2
return x; // will move
throw x; // will move
}
25
Два слова об эффективности
template<class T>
bool has_duplicates(const std::vector<T>& v) {
std::vector<T> tmp = v;
std::sort(tmp.begin(), tmp.end());
return std::unique(tmp.begin(), tmp.end()) != tmp.end();
}
std::vector<int> read_file(const char* filename);
bool has_duplicates_in_file(const char* filename) {
return has_duplicates(read_file(filename));
}
26
Два слова об эффективности
template<class T>
bool has_duplicates(std::vector<T> v) {
std::sort(v.begin(), v.end());
return std::unique(v.begin(), v.end()) != v.end();
}
std::vector<int> read_file(const char* filename);
bool has_duplicates_in_file(const char* filename) {
return has_duplicates(read_file(filename));
}
27
Два слова об эффективности
!  Обещанные два слова:
Не парьтесь!
!  Пишите то, что думаете:
–  f(const X&) – «я только спросить»;
–  f(X) – «мне нужна локальная копия»;
!  Позвольте компилятору позаботиться об остальном.
28
Переместить неперемещаемое
class X {
public:
X();
X(const X&);
};
void f(X);
void g() {
X x;
f(std::move(x));
}
! std::move – это разрешение компилятору выполнить
перемещение;
!  «Не можешь переместить? Скопируй!»
29
...и исключения
30
Снова std::vector
template<class T> class vector { // not really
private:
T *start, *finish, *storage_end;
void reallocate(size_t new_capacity);
public:
size_t capacity() const { return storage_end - start; }
void push_back(T t) {
if (finish == storage_end) {
reallocate((capacity() + 1) * 2);
}
new(finish) T(std::move(t));
++finish;
}
};
31
Снова std::vector
template<class T>
void vector<T>::reallocate(size_t new_capacity) {
T* new_storage = malloc(new_capacity * sizeof(T));
T* dest = new_storage;
try {
for (T* p = start; p != finish; ++p, ++dest)
new(dest) T(std::move(*p));
for (T* p = start; p != finish; ++p)
p->~T();
free(start);
// apply things...
}
catch (...) {
for (T* p = new_storage; p != dest; ++p)
p->~T();
free(new_storage);
throw;
}
}
32
!  Оригинальный набор объектов не изменяется;
!  Тривиально обеспечить строгую гарантию.
Копируем несколько объектов
33
!  Оригинальный набор объектов портится;
!  Невозможно обеспечить гарантию лучше базовой;
–  Иногда даже базовую гарантию обеспечить не получается.
Перемещаем несколько объектов
34
Перемещающие операции
не ошибаются!
35
Но если очень хочется?
template<class X, class Y>
struct pair {
X first;
Y second;
// compiler-generated
pair(pair<X, Y>&& p):
first(std::move(p.first)),
second(std::move(p.second))
{}
};
!  Всё ли здесь в порядке?
!  А если для Y не определены перемещающие операции?
36
Throw specifiers strike back!
Новое ключевое слово: noexcept
! f() noexcept – не может кидать исключений;
! f() noexcept(<cond>) – не может кидать исключений, если
<cond> == true;
! noexcept(<expr>) – это bool, равный true, если вычисление
<expr> не может кидать исключений.
–  ...то есть вызывает только операции над примитивными типами и
функции, отмеченные как noexcept или throw().
37
...плюс пара trait-ов...
template<class T>
struct is_nothrow_move_constructible { // not really
static bool value = noexcept(
new(std:nothrow) T(std::move(*(T*)0)));
};
template<class T>
conditional<
is_no_throw_move_constructible<T>::value,
T&&, const T&
> move_if_noexcept(T&);
38
...и имеем строгую гарантию
template<class T>
void vector<T>::reallocate(size_t new_capacity) {
// ...skipped...
for (T* p = start; p != finish; ++p, ++dest)
new(dest) T(std::move_if_noexcept(*p));
// ...skipped...
}
39
Это не бесплатно
!  Если f() noexcept всё-таки попробует выкинуть исключение –
вызовется std::terminate();
–  компилятор вынужден оборачивать каждую такую функцию
в try-block;
!  Если компилятор не может доказать безопасность
перемещения – он переключится на копирование.
40
Это не бесплатно
!  Если вы пишете свои контейнеры -- не увлекайтесь!
–  «Строгая, кроме случаев, когда перемещающие операции
могут генерировать исключения» -- вполне достаточная
гарантия.
!  Но перемещающие операции своих классов отмечать как
noexcept всё-таки надо.
–  Сгенерированный компилятором метод сам получит такую
метку, если нужно.
41
Универсальные ссылки
42
Reference collapsing
typedef cosnt X& XL;
typedef XL& XLL;
typedef volatile XLL& XLLL;
// XLL = const volatile X&
! const ((volatile X&) &) & = const volatile X&
!  (X&&) && = X&&
!  (X&) && = (X&&) & = X&
43
...и выведение типов
template<class T> void f(T&&);
const X& cx = /*...*/; f(cx); // T = const X&
X& lx = /*...*/; f(lx); // T = X&
X x; f(x); // T = X&
f(std::move(x)); // T = X
X fx(); f(fx()); // T = X
44
T&& + выведение типа
= универсальная ссылка
45
Задача о перенаправлении*
!  Дано: функция от одного аргумента и аргумент.
!  Задача: вызвать функцию от этого аргумента.
template<class F, class Arg>
void call(F f, Arg arg) { f(arg); }
!  Если f(x) компилируется – то call(f, x) тоже должна
компилироваться и делать то же самое;
!  Если f(x) не компилируется – то call(f, x) тоже не должна.
!  Мы ничего не знаем ни про f, ни про x.
(*англ.	
  forwarding)	
  
46
Как принимать аргумент?
! void call(F f, Arg&);
// нельзя вызывать с временными объектами;
! void call(F f, const Arg&);
// не работает, если f() принимает неконстантную ссылку;
! void call(F f, const Arg&); void call(F f, Arg&);
// а если у функции восемь аргументов?
! void call(F f, Arg arg);
// молча всё ломает, если f() принимает Arg& и меняет его;
! void call(F f, const Arg& arg) { f(const_cast<Arg&>(arg); }
// сегфолтится.
! void call(F f, Arg&& arg);
// бинго!
47
Почти идеальный forwarding
template<class F, class Arg>
void call(F f, Arg&& arg) { f(arg); }
void gl(X&);
void gcl(const X&);
void gr(X);
Выражение	
   Выведенный	
  
тип	
  Arg	
  
Вид	
  функции	
  call()	
  
X	
  x;	
  
call(gl,	
  x);	
  
X&	
   call(F	
  f,	
  X&	
  x)	
  {	
  f(x);	
  }	
  
const	
  X&	
  cx;	
  
call(gcl,	
  cx);	
  
const	
  X&	
   call(F	
  f,	
  const	
  X&	
  x)	
  {	
  f(x);	
  }	
  
X	
  fx();	
  
call(gr,	
  fx());	
  
X	
   call(F	
  f,	
  X&&	
  x)	
  {	
  f(x);	
  }	
  
X	
  x;	
  
call(gr,	
  std::move(x));	
  
X	
   call(F	
  f,	
  X&&	
  x)	
  {	
  f(x);	
  }	
  
Не	
  хватает	
  
std::move()	
  
48
Идеальный forwarding
template<class F, class Arg>
void call(F f, Arg&& arg)
{
f(static_cast<Arg&&>(arg));
f(std::forward<Arg>(arg));
}
49
Зачем это всё?
template<class T> class vector {
public:
template<class... Args>
void emplace_back(Args&&... args) {
if (finish == storage_end)
reallocate(capacity()*2);
new(finish) T(std::forward<Args>(args)...);
++finish;
}
};
50
std::forward() ≠ std::move()
! template<class T>
typename remove_reference<T>::value&&
move(T&& t);
! template<class T>
T&& forward(typename std::identity<T>::type&& t);
! move()	
  всегда	
  приводит	
  свой	
  аргумент	
  к	
  правой	
  сслыке;	
  
! forward()	
  делает	
  это,	
  если	
  только	
  его	
  шаблонный	
  аргумент	
  –	
  не	
  
левая	
  ссылка.	
  
51
std::move() ≠ std::forward()
X	
  x;	
   move(x)	
   X&&	
  
forward<X>(x)	
   X&&	
  
	
  
const	
  X&	
  cx;	
   move(cx)	
   const	
  X&&	
  /*???*/	
  
forward<const	
  X&>(cx)	
   const	
  X&	
  
	
  
X&	
  lx;	
   move(lx)	
   X&&	
  
forward<X&>(lx)	
   X&	
  
	
  
X&&	
  rx;	
   move(rx)	
   X&&	
  
foward<X&&>(rx)	
   (не	
  бывает)	
  
forward(x)	
   compile	
  error	
  
52
Спасибо за внимание!
53
Дмитрий Прокопцев
dprokoptsev@yandex-team.ru
http://github.com/dprokoptsev
Яндекс.Карты,
старший разработчик

More Related Content

What's hot

Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Mikhail Kurnosov
 

What's hot (20)

Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
 
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_cast
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
 
Python&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.by
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормоза
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
 
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
 
Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6Объектно-ориентированное программирование. Лекция 5 и 6
Объектно-ориентированное программирование. Лекция 5 и 6
 
Максим Хижинский Lock-free maps
Максим Хижинский Lock-free mapsМаксим Хижинский Lock-free maps
Максим Хижинский Lock-free maps
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
Антон Полухин, Немного о Boost
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о Boost
 
Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8. Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8.
 
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
 

Similar to Дмитрий Прокопцев — R-ссылки в С++11

Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
Andrey Karpov
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
Computer Science Club
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
Andrey Karpov
 
Deep Dive C# by Sergey Teplyakov
Deep Dive  C# by Sergey TeplyakovDeep Dive  C# by Sergey Teplyakov
Deep Dive C# by Sergey Teplyakov
Alex Tumanoff
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU
 

Similar to Дмитрий Прокопцев — R-ссылки в С++11 (20)

Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
 
Cpp0x Introduction
Cpp0x IntroductionCpp0x Introduction
Cpp0x Introduction
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
 
Clojure #2 (2014)
Clojure #2 (2014)Clojure #2 (2014)
Clojure #2 (2014)
 
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
Метапрограммирование в C++11/14 и C++17. Новые инструменты - новые проблемы.
 
Parallel STL
Parallel STLParallel STL
Parallel STL
 
Rust: абстракции и безопасность, совершенно бесплатно
Rust: абстракции и безопасность, совершенно бесплатноRust: абстракции и безопасность, совершенно бесплатно
Rust: абстракции и безопасность, совершенно бесплатно
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
 
Document
DocumentDocument
Document
 
DSLs in Lisp and Clojure
DSLs in Lisp and ClojureDSLs in Lisp and Clojure
DSLs in Lisp and Clojure
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
ПВТ - весна 2015 - Лекция 1. Актуальность параллельных вычислений. Анализ пар...
ПВТ - весна 2015 - Лекция 1. Актуальность параллельных вычислений. Анализ пар...ПВТ - весна 2015 - Лекция 1. Актуальность параллельных вычислений. Анализ пар...
ПВТ - весна 2015 - Лекция 1. Актуальность параллельных вычислений. Анализ пар...
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
Продолжаем говорить о микрооптимизациях .NET-приложений
Продолжаем говорить о микрооптимизациях .NET-приложенийПродолжаем говорить о микрооптимизациях .NET-приложений
Продолжаем говорить о микрооптимизациях .NET-приложений
 
Tricky Java Generics
Tricky Java GenericsTricky Java Generics
Tricky Java Generics
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода
 
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
 
Deep Dive C# by Sergey Teplyakov
Deep Dive  C# by Sergey TeplyakovDeep Dive  C# by Sergey Teplyakov
Deep Dive C# by Sergey Teplyakov
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
 

More from Yandex

Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Yandex
 
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров ЯндексаСтруктурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Yandex
 
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров ЯндексаПредставление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Yandex
 
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Yandex
 
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Yandex
 
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Yandex
 
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Yandex
 
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Yandex
 
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Yandex
 
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Yandex
 
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Yandex
 
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеровКак защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Yandex
 
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Yandex
 
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Yandex
 
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Yandex
 
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Yandex
 
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Yandex
 
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Yandex
 
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Yandex
 

More from Yandex (20)

Предсказание оттока игроков из World of Tanks
Предсказание оттока игроков из World of TanksПредсказание оттока игроков из World of Tanks
Предсказание оттока игроков из World of Tanks
 
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
 
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров ЯндексаСтруктурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
 
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров ЯндексаПредставление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
 
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
 
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
 
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
 
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
 
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
 
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
 
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
 
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
 
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеровКак защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
 
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
 
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
 
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
 
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
 
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
 
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
 
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
 

Дмитрий Прокопцев — R-ссылки в С++11

  • 1. 1
  • 2. 2 карты Rvalue references in C++11 Дмитрий Прокопцев Яндекс.Карты, старший разработчик
  • 3. 3 Кто мы такие Пишем на С++11 с 2010 года; Продирались через черновики стандарта; Набили шишек и получили опыт :)
  • 4. 4 Краткое содержание !  Зачем всё это нужно? !  Новые ссылки в языке !  Перемещение классов !  Как быть с исключениями !  Универсальные ссылки
  • 5. 5 Зачем? !  Скорость работы: –  std::vector<X> v = vector_with_400M_items(); !  Семантическая ясность: –  std::unique_ptr<X> make_x(); –  std::thread spawn_thread(); –  std::iostream tcp_connect(const std::string& addr);
  • 6. 6 Но ведь уже было? template<class T> class auto_ptr { private: T* held; public: // needed for ‘auto_ptr<X> y2 = y1’ auto_ptr(auto_ptr<X>& other) { held = other.held; other.held = 0; } // see next page... };
  • 7. 7 Но ведь уже было? template<class T> class auto_ptr { // cont’d public: // needed for ‘auto_ptr<X> x = f()’ struct auto_ptr_ref { auto_ptr<T>* ptr; auto_ptr_ref(auto_ptr<T>* self): ptr(self) {} }; operator auto_ptr_ref() { return auto_ptr_ref(this); } auto_ptr(auto_ptr_ref ref) { held = ref.ptr->held; ref.ptr->held = 0; } };
  • 8. 8 Но ведь уже было? !  Одни и те же 10 строк для каждого класса; !  Семантическая неоднозначность: –  std::vector<char> v2 = v1; // копирование –  std::auto_ptr<X> p2 = p1; // перемещение –  template<class X> void f(X& x) { X y = x; // копирование? перемещение? }
  • 9. 9 Ревизия ссылок ! T::T(const T&) –  Копирование; –  Может быть вызвано и от lvalues, и от временных объектов; ! T::T(T&) –  Подразумеваемое перемещение (по стандарту -- копирование); –  Ссылка связывается только с lvalues, не позволяет перемещать из временных объектов. ! T::T(T_ref) –  Подразумеваемое перемещение; –  T_ref «связывается» и с lvalues, и с rvalues;
  • 11. 11 Что к чему приводится F(X&)   F(const  X&)   F(X&&)   x   xlref   fxlref()   Да   Если  нужно   sta6c_cast   xclref   fxclref()   Нет   Да   Нет   fx()   fxrref()   Нет   Если  нужно   Да   xrref   Да   Если  нужно   sta6c_cast   X  x;   X&  xlref  =  /*...*/;   const  X&  xclref  =  /*...*/;   X&&  xrref  =  /*...*/;   X  fx();   X&  fxlref();   const  X&  fxclref();   X&&  xrref();  
  • 12. 12 Что к чему приводится F(X&)   F(const  X&)   F(X&&)   x   xlref   fxlref()   Да   Да   sta6c_cast   xclref   fxclref()   Нет   Да   Нет   fx()   fxrref()   Нет   Если  нужно   Да   xrref   Да   Да   sta6c_cast   X  x;   X&  xlref  =  /*...*/;   const  X&  xclref  =  /*...*/;   X&&  xrref  =  /*...*/;   X  fx();   X&  fxlref();   const  X&  fxclref();   X&&  xrref();  
  • 13. 13 Можно грабить корованы классы template<class T> bool has_duplicates(const std::vector<T>& v) { // make a copy and play with it std::vector<T> tmp = v; std::sort(tmp.begin(), tmp.end()); return std::unique(tmp.begin(), tmp.end()) != tmp.end(); } template<class T> bool has_duplicates(std::vector<T>&& v) { // ‘v’ points to a temporary; no need to make a copy std::sort(v.begin(), v.end()); return std::unique(v.begin(), v.end()) != v.end(); }
  • 15. 15 Перемещающие операции ! T::T(const T&); –  копирующий конструктор; ! T& T::operator = (const T&); –  копирующее присваивание; ! T(T&&); –  перемещающий конструктор; ! T& T::operator = (T&&); –  перемещающее присваивание.
  • 16. 16 Пример: std::vector template<class T> class vector { // not really private: T *start, *finish, *storage_end; public: vector(const vector<T>&); // omitted vector& operator = (const vector<T>&); // omitted vector(vector<T>&& v): start(v.start), finish(v.finish), storage_end(v.storage_end) { v.start = v.finish = v.storage_end = 0; } vector<T>& operator = (vector<T>&& v) { std::swap(start, v.start); std::swap(finish, v.finish); std::swap(storage_end, v.storage_end); } };
  • 17. 17 Время жизни объекта, из которого выполнили перемещение, не заканчивается!
  • 18. 18 Вспоминаем Майерса «Если вашему классу нужен пользовательский конструктор копирования, оператор копирующего присваивания, конструктор перемещения, оператор перемещающего присваивания или деструктор -- скорее всего, ему нужно всё вышеперечисленное.»
  • 19. 19 Делать ли класс перемещаемым? !  Перемещающее присваивание можно сделать всегда; –  достаточно обменять все поля класса; !  Перемещающий конструктор требует наличия пустого состояния; –  оно моделируется пустым конструктором; !  Перемещающее присваивание без перемещающего конструктора выглядит странно; !  Если у класса нет допустимого пустого состояния –- проще целиком запретить перемещение.
  • 20. 20 Базис класса !  Класс перемещаемый –  T::T(); –  T::T(const T&); –  T& T::operator = (T&&); –  T::T(T&& t): T() { *this = static_cast<T&&>(t); } –  T& T::operator = (const T&) { return *this = T(t); } !  Класс неперемещаемый: –  T::T(const T&); –  void T::swap(T&); –  T& T::operator = (const T&) { T(t).swap(*this); return *this; }
  • 21. 21 Автогенерация методов !  Если у класса нет недефолтных копирующих методов или деструктора -- компилятор сгенерирует перемещающие методы сам; !  Если у класса есть пользовательские перемещающие методы -- копирующие методы генерироваться не будут. !  Всегда можно попросить компилятор сгенерировать метод: –  T(T&&) = default; –  T& operator = (T&&) = default;
  • 22. 22 Заботливо разложенные грабли class screen { // came from year 2004 private: std::vector< std::vector<char> > chars; public: screen(): chars(25, std::vector<char>(80, ‘x20’)) {} void put_char(int x, int y, char c) { chars[y][x] = c; } };
  • 23. 23 Если  у  класса  есть  инвариант,   не  являющийся  следствием  инвариантов  всех  его   полей  и  баз  –   перемещение  классу  нужно  писать  руками!  
  • 24. 24 Перемещение из переменных void f(const X&); // #1 void f(X&&); // #2 void g() { X x; f(x); // uses #1 f(static_cast<X&&>(x)); // uses #2 f(std::move(x)); // uses #2 return x; // will move throw x; // will move }
  • 25. 25 Два слова об эффективности template<class T> bool has_duplicates(const std::vector<T>& v) { std::vector<T> tmp = v; std::sort(tmp.begin(), tmp.end()); return std::unique(tmp.begin(), tmp.end()) != tmp.end(); } std::vector<int> read_file(const char* filename); bool has_duplicates_in_file(const char* filename) { return has_duplicates(read_file(filename)); }
  • 26. 26 Два слова об эффективности template<class T> bool has_duplicates(std::vector<T> v) { std::sort(v.begin(), v.end()); return std::unique(v.begin(), v.end()) != v.end(); } std::vector<int> read_file(const char* filename); bool has_duplicates_in_file(const char* filename) { return has_duplicates(read_file(filename)); }
  • 27. 27 Два слова об эффективности !  Обещанные два слова: Не парьтесь! !  Пишите то, что думаете: –  f(const X&) – «я только спросить»; –  f(X) – «мне нужна локальная копия»; !  Позвольте компилятору позаботиться об остальном.
  • 28. 28 Переместить неперемещаемое class X { public: X(); X(const X&); }; void f(X); void g() { X x; f(std::move(x)); } ! std::move – это разрешение компилятору выполнить перемещение; !  «Не можешь переместить? Скопируй!»
  • 30. 30 Снова std::vector template<class T> class vector { // not really private: T *start, *finish, *storage_end; void reallocate(size_t new_capacity); public: size_t capacity() const { return storage_end - start; } void push_back(T t) { if (finish == storage_end) { reallocate((capacity() + 1) * 2); } new(finish) T(std::move(t)); ++finish; } };
  • 31. 31 Снова std::vector template<class T> void vector<T>::reallocate(size_t new_capacity) { T* new_storage = malloc(new_capacity * sizeof(T)); T* dest = new_storage; try { for (T* p = start; p != finish; ++p, ++dest) new(dest) T(std::move(*p)); for (T* p = start; p != finish; ++p) p->~T(); free(start); // apply things... } catch (...) { for (T* p = new_storage; p != dest; ++p) p->~T(); free(new_storage); throw; } }
  • 32. 32 !  Оригинальный набор объектов не изменяется; !  Тривиально обеспечить строгую гарантию. Копируем несколько объектов
  • 33. 33 !  Оригинальный набор объектов портится; !  Невозможно обеспечить гарантию лучше базовой; –  Иногда даже базовую гарантию обеспечить не получается. Перемещаем несколько объектов
  • 35. 35 Но если очень хочется? template<class X, class Y> struct pair { X first; Y second; // compiler-generated pair(pair<X, Y>&& p): first(std::move(p.first)), second(std::move(p.second)) {} }; !  Всё ли здесь в порядке? !  А если для Y не определены перемещающие операции?
  • 36. 36 Throw specifiers strike back! Новое ключевое слово: noexcept ! f() noexcept – не может кидать исключений; ! f() noexcept(<cond>) – не может кидать исключений, если <cond> == true; ! noexcept(<expr>) – это bool, равный true, если вычисление <expr> не может кидать исключений. –  ...то есть вызывает только операции над примитивными типами и функции, отмеченные как noexcept или throw().
  • 37. 37 ...плюс пара trait-ов... template<class T> struct is_nothrow_move_constructible { // not really static bool value = noexcept( new(std:nothrow) T(std::move(*(T*)0))); }; template<class T> conditional< is_no_throw_move_constructible<T>::value, T&&, const T& > move_if_noexcept(T&);
  • 38. 38 ...и имеем строгую гарантию template<class T> void vector<T>::reallocate(size_t new_capacity) { // ...skipped... for (T* p = start; p != finish; ++p, ++dest) new(dest) T(std::move_if_noexcept(*p)); // ...skipped... }
  • 39. 39 Это не бесплатно !  Если f() noexcept всё-таки попробует выкинуть исключение – вызовется std::terminate(); –  компилятор вынужден оборачивать каждую такую функцию в try-block; !  Если компилятор не может доказать безопасность перемещения – он переключится на копирование.
  • 40. 40 Это не бесплатно !  Если вы пишете свои контейнеры -- не увлекайтесь! –  «Строгая, кроме случаев, когда перемещающие операции могут генерировать исключения» -- вполне достаточная гарантия. !  Но перемещающие операции своих классов отмечать как noexcept всё-таки надо. –  Сгенерированный компилятором метод сам получит такую метку, если нужно.
  • 42. 42 Reference collapsing typedef cosnt X& XL; typedef XL& XLL; typedef volatile XLL& XLLL; // XLL = const volatile X& ! const ((volatile X&) &) & = const volatile X& !  (X&&) && = X&& !  (X&) && = (X&&) & = X&
  • 43. 43 ...и выведение типов template<class T> void f(T&&); const X& cx = /*...*/; f(cx); // T = const X& X& lx = /*...*/; f(lx); // T = X& X x; f(x); // T = X& f(std::move(x)); // T = X X fx(); f(fx()); // T = X
  • 44. 44 T&& + выведение типа = универсальная ссылка
  • 45. 45 Задача о перенаправлении* !  Дано: функция от одного аргумента и аргумент. !  Задача: вызвать функцию от этого аргумента. template<class F, class Arg> void call(F f, Arg arg) { f(arg); } !  Если f(x) компилируется – то call(f, x) тоже должна компилироваться и делать то же самое; !  Если f(x) не компилируется – то call(f, x) тоже не должна. !  Мы ничего не знаем ни про f, ни про x. (*англ.  forwarding)  
  • 46. 46 Как принимать аргумент? ! void call(F f, Arg&); // нельзя вызывать с временными объектами; ! void call(F f, const Arg&); // не работает, если f() принимает неконстантную ссылку; ! void call(F f, const Arg&); void call(F f, Arg&); // а если у функции восемь аргументов? ! void call(F f, Arg arg); // молча всё ломает, если f() принимает Arg& и меняет его; ! void call(F f, const Arg& arg) { f(const_cast<Arg&>(arg); } // сегфолтится. ! void call(F f, Arg&& arg); // бинго!
  • 47. 47 Почти идеальный forwarding template<class F, class Arg> void call(F f, Arg&& arg) { f(arg); } void gl(X&); void gcl(const X&); void gr(X); Выражение   Выведенный   тип  Arg   Вид  функции  call()   X  x;   call(gl,  x);   X&   call(F  f,  X&  x)  {  f(x);  }   const  X&  cx;   call(gcl,  cx);   const  X&   call(F  f,  const  X&  x)  {  f(x);  }   X  fx();   call(gr,  fx());   X   call(F  f,  X&&  x)  {  f(x);  }   X  x;   call(gr,  std::move(x));   X   call(F  f,  X&&  x)  {  f(x);  }   Не  хватает   std::move()  
  • 48. 48 Идеальный forwarding template<class F, class Arg> void call(F f, Arg&& arg) { f(static_cast<Arg&&>(arg)); f(std::forward<Arg>(arg)); }
  • 49. 49 Зачем это всё? template<class T> class vector { public: template<class... Args> void emplace_back(Args&&... args) { if (finish == storage_end) reallocate(capacity()*2); new(finish) T(std::forward<Args>(args)...); ++finish; } };
  • 50. 50 std::forward() ≠ std::move() ! template<class T> typename remove_reference<T>::value&& move(T&& t); ! template<class T> T&& forward(typename std::identity<T>::type&& t); ! move()  всегда  приводит  свой  аргумент  к  правой  сслыке;   ! forward()  делает  это,  если  только  его  шаблонный  аргумент  –  не   левая  ссылка.  
  • 51. 51 std::move() ≠ std::forward() X  x;   move(x)   X&&   forward<X>(x)   X&&     const  X&  cx;   move(cx)   const  X&&  /*???*/   forward<const  X&>(cx)   const  X&     X&  lx;   move(lx)   X&&   forward<X&>(lx)   X&     X&&  rx;   move(rx)   X&&   foward<X&&>(rx)   (не  бывает)   forward(x)   compile  error