foreach
Как раскрыть? v.begin()
, v.end()
не применим для массивов например. Выход простой — запилить внешнюю перегрузку std::begin(v)
, std::end(v)
, std::size(v)
Когда расширяешь язык, можно многое забыть
template<typename T> std::vector<T>::const_iterator f(std::vector<T> const &v) {}
void g(std::vector<int> &v) { std::find(f(v), v.end(), 5) }
Не работает, ибо разные типы итераторов, поэтому потом добавили .cend()
, .cbegin()
и т.д.
Но забыли добавить std::cbegin(v)
И т.д, хех (вроде в с++11)
Еще забыли в лямбдах разрешать move
[a] {...}
[&a] {...}
Потом добавили [a = std::move(a)] {}
, где инициализатором может быть все что угодно
Еще в initializer_list
не предусмотрен move, если написать
string s;
std::vector<string> a = {"foo", "bar", std::move(s)}
то в итоге s скопируется сначала в лист, а потом в вектор — два копирования вместо мува, хыхы
.so загружается не всегда по одному адресу. Проблема — мы не можем в машинном коде знать адрес переменных. Для статики легко — просто смотрим на разницу адресов.
Можно попробовать хранить в регистре в какой адрес мы загрузились, но тогда надо аккуратно все перетирать регистры при вызове длл из длл (вроде), плюс может использоваться прослойка для вызова функции и иногда вместо адреса функции мы получим адрес прослойки
Можно хранить таблицу релокаций — просто загрузить программу, пройтись по всем внешним функциям, переправить адреса, но это замедляет старт программы (в винде вроде что-то такое, но они просто инкрементят на address - base_address
). Еще проблема — если загрузилось в base_address
, то шарится между всеми процессами, иначе у каждого процесса своя копия дллки.
В линухе есть GOT (global offset table) — чтобы не править всю программу собирается то, что зависит от адресов программы, и правим мы уже GOT. Но вот проблема — как обращаться к GOT’у? (используется для чего-то другого, хз для чего)
Еще один выход. У нас есть jmp
, казалось бы для него такая же проблема с адресами? Нет, он использует относительный адрес, поэтому ему пофиг (и call
тоже). Так а почему бы и память не читать относительно? На 64-битных системах появились такие команды, поэтому мы можем сгенерить код на относительных адресах (PIC (position independent code)).
А что делать с 32-битными системами?( В линуксе такой код генерится и для 32-бит, но обращение делается неэффективно. Делают call
на некоторую функцию, которая возвращает адрес этой функции и зная относительные адреса херачим.
Когда запускаете программу — запускается не ваша программа, а динамический загрузчик (в линухе что-то вроде ld-linux.so
) и ваша программа передается ему как аргумент. И в линухе просят “дайте мне кто-нибудь эту функцию”, а динамический загрузчик как-то выбирает из .so
приоритеты.