Перейти к содержимому
Теория · Многопоточность: обзор · урок 11 из 12

Длительности: 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;.

C++
#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 по строкам:

  1. 2min + 30s складывает минуты с секундами. Сумма получает тип более мелкой из двух единиц, то есть секунды, и в total попадает 150 секунд.
  2. std::chrono::milliseconds ms = total; переводит секунды в миллисекунды: 150000.
  3. .count() у каждой длительности возвращает её число единиц, и программа печатает 150 150000.

В крупные единицы — явно

Перевод единиц похож на размен денег. Рубли в копейки разменять можно всегда и без потерь. Копейки в рубли — только с остатком: 150 копеек — это рубль, а ещё 50 копеек в целый рубль не помещаются.

С длительностями так же:

  • в более мелкие единицы длительность переводится сама: точность при этом не теряется;
  • обратный перевод может потерять дробную часть, поэтому его пишут явно, через std::chrono::duration_cast.

duration_cast округляет к нулю: std::chrono::duration_cast<std::chrono::seconds>(1500ms) равно 1s. Здесь аналогия с деньгами заканчивается: остаток копеек остаётся у вас в кармане, а duration_cast его отбрасывает без следа.

Частая ошибка

Миллисекунды присваивают секундам:

C++
std::chrono::milliseconds ms{1500};
std::chrono::seconds s = ms;  // ✗
TEXT
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 и подпишись на канал — откроются все уроки.

Войти другим способом