Длительности: chrono
Рецепт говорит: варить 2 минуты 30 секунд. Кухонный таймер считает секунды, поэтому повар переводит время и ставит 150. Если перепутать единицы и поставить 150 минут, суп выкипит. В программе время тоже хранят вместе с единицами, и путаница единиц — частая ошибка.
Потоку часто нужно подождать: std::this_thread::sleep_for приостанавливает его на заданную длительность. Длительность — это число вместе с единицей измерения. Её задают типы из заголовка <chrono>:
std::chrono::minutes— минуты;std::chrono::seconds— секунды;std::chrono::milliseconds— тысячные доли секунды.
Метод .count() возвращает число единиц. Литералы 2min, 30s и 500ms доступны после строки using namespace std::chrono_literals;.
#include <chrono>
#include <iostream>
using namespace std::chrono_literals;
int main() {
std::chrono::seconds total = 2min + 30s;
std::chrono::milliseconds ms = total;
std::cout << total.count() << ' ' << ms.count() << '\n'; // 150 150000
}Давайте разберём main по строкам:
2min + 30sскладывает минуты с секундами. Сумма получает тип более мелкой из двух единиц, то есть секунды, и вtotalпопадает150секунд.std::chrono::milliseconds ms = total;переводит секунды в миллисекунды:150000..count()у каждой длительности возвращает её число единиц, и программа печатает150 150000.
В крупные единицы — явно
Перевод единиц похож на размен денег. Рубли в копейки разменять можно всегда и без потерь. Копейки в рубли — только с остатком: 150 копеек — это рубль, а ещё 50 копеек в целый рубль не помещаются.
С длительностями так же:
- в более мелкие единицы длительность переводится сама: точность при этом не теряется;
- обратный перевод может потерять дробную часть, поэтому его пишут явно, через
std::chrono::duration_cast.
duration_cast округляет к нулю: std::chrono::duration_cast<std::chrono::seconds>(1500ms) равно 1s. Здесь аналогия с деньгами заканчивается: остаток копеек остаётся у вас в кармане, а duration_cast его отбрасывает без следа.
Частая ошибка
Миллисекунды присваивают секундам:
std::chrono::milliseconds ms{1500};
std::chrono::seconds s = ms; // ✗error: no viable conversion from 'duration<[...], ratio<[...], 1000>>' to 'duration<[...], ratio<[...], 1>>'Это ошибка компиляции: программа не собирается. В сообщении std::chrono::milliseconds и std::chrono::seconds названы своими полными типами: ratio<…, 1000> — тысячные доли секунды, ratio<…, 1> — целые секунды.
Компилятор проверяет типы, а не значение: перевод миллисекунд в секунды может потерять дробную часть, даже если бы в ms было ровно 2000. Если потеря допустима, переведите через duration_cast.
Главное
- Длительность — число вместе с единицей:
std::chrono::seconds,std::chrono::milliseconds,std::chrono::minutes;.count()возвращает число единиц. - Литералы
30s,500msи2minработают послеusing namespace std::chrono_literals;. - В более мелкие единицы длительность переводится сама, а в более крупные — только через
duration_cast. duration_castокругляет к нулю:1500msпревращается в1s.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.