TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #713 4.39K
decltype(auto) vs auto&&. Прокси объекты и висячие ссылки.
#опытным

В прошлом посте мы видели, что разница в использовании decltype(auto) и auto&& при выводе типа возвращаемого значения функции проявляется только при возврате объектов, на которые явно не навесили ссылки. Иногда мы можем это отследить глазами и потенциально использовать более простую версию вывода типа. Однако не все мы можем отследить глазами.

Доступ к элементам std::deque всегда возвращает честную левую ссылку. И это почти полностью справедливо для std::vector, кроме одного исключения.

Это std::vector<bool>. Эта специализация вектора возвращает не честную ссылку на объект типа bool, в временный proxy объект. Дело в том, что тип bool занимает как минимум 1 байт, так как это минимально адресуемая ячейка памяти. Но логически он хранит всего 1 бит информации. Если бы мы могли как-то по-хитрому хранить булевы значения, чтобы каждое из них занимало всего 1 бит, то мы бы уменьшили потребление памяти как минимум в 8 раз! Именно это и делается в специализации для bool. Там булевы значения хранятся в виде битов более вместительного типа(int), а для получения доступа к значениям используется proxy объект reference, который неявно приводится bool.

Посмотрим, к чему приводит эта маленькая особенность:

template<typename Container, typename Index>
auto&& processAndAccess(Container& c, Index i) {
// do something
// ...
return c[i];
}

std::vector<int> v = {1, 2, 3};
// OK - returns int&
processAndAccess(v, 1) = 3;

std::vector<bool> v2 = {true, false, false};
// NOT OK - returns vector<bool>::reference&& which is a dangling reference
processAndAccess(v2, 1) = true;


Для инстанциаций вектора с любыми другими типами все хорошо работает. А для bool специализации мы получаем висячую ссылку и UB.


При использовании decltype(auto) таких проблем нет. Можете поиграться с примерами на cppinsights и godbolt.

Proxy объекты не так часто используются. Один из основных кейсов - это доступ к элементам многомерных структур. Однако при проектировании и написании кода, которым будут пользоваться другие люди, нужно учитывать такие вещи и писать в первую очередь безопасный код.

Спасибо @thonease за предоставления исходного кода)

По итогу серии постов: использование auto&& безопасно при выводе типа локального объекта, но небезопасно при выводе типа возвращаемого значения функции. В последнем случае нужно использовать decltype(auto).

Be safe. Stay cool.

#cppcore #template
  • 🔥 18
  • 👍 12
  • ❤ 9
More from @grokaemcpp
  1. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  2. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  3. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  4. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  5. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  6. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →