Почему сетевые запросы нельзя отправлять в главном потоке

Ответ

Ответ не найден

Ответ 18+ 🔞

А, ну это же классика, блядь! Сейчас объясню, в чём тут соль, а то ты, наверное, как тот самый Фарлаф, только объёбку ищешь, а суть упускаешь.

Смотри, есть у нас в языке такая штука — std::move. Имя, конечно, пиздопроебибное, сразу волнение ебать начинается: «О, двигать! Перемещать!». А на деле-то он нихуя не двигает. Вообще. Ничего. Это, блядь, ключевой момент, который все путают.

Представь себе коробку с игрушкой. std::move — это не грузчик, который берёт эту коробку и тащит её на другое место. Это больше похоже на хитрую бумажку, которую ты на эту коробку наклеиваешь. На бумажке написано: «Эй, чувак, который будет читать этот код! Эту коробку можно забрать всё содержимое нахер, потому что старому хозяину оно больше не нужно».

Вот и вся магия. Это просто приведение типа. Конкретно — к rvalue-ссылке (T&&). Он говорит компилятору: «Смотри, этот объект — временный (или мы делаем вид, что он временный), с ним можно делать всё, что можно с временным, например, украсть у него ресурсы вместо того, чтобы копировать».

std::string source = "Hello";
std::string destination = std::move(source);
// После этой операции состояние `source` не определено!
// Оно "valid but unspecified". Может быть пустым, а может там "Hello" остаться.
// Но рассчитывать на это — идиотизм. Считай, что source теперь пустой.

Вот тут многие сам от себя охуевают: они думают, что после std::move(source) в source всё ещё будет «Hello». А там, ёпта, может быть чёрт знает что! Он отдал право новому объекту выпотрошить себя, как тухлую рыбу.

Зачем это нужно? Да затем, чтобы не копировать дорогие штуки, типа динамических массивов внутри std::vector или строк. Вместо копирования всего массива, мы просто переставляем указатели на эту память. Старый объект остаётся «битым», зато новый получает ресурсы мгновенно и почти бесплатно. Это и есть перемещающая семантика (move semantics).

Но запомни, как Отче наш: std::move сам по себе — это просто наклейка. Перемещение реально произойдёт только если есть перемещающий конструктор или перемещающий оператор присваивания (Class(Class&&) или Class& operator=(Class&&)). Если их нет — компилятор просто скопирует, как обычно, и вся твоя хитрая жопа с std::move будет просто бесполезным трюком.

Короче, резюмирую, чтобы в душу мать не било:

  1. std::move — не двигает. Он только разрешает потенциальное перемещение.
  2. Он не гарантирует, что перемещение произойдёт (нужен подходящий конструктор).
  3. После std::move объект отдан на растерзание. Не используй его, не убедившись, что он в валидном состоянии (обычно просто присваивай новое значение).

Понял? Если нет — да похуй, иди перечитывай. А то будешь как тот Гамлет, всех нахуй посылать, а в коде у тебя манда с ушами получится вместо оптимизации.