2016-02-05 2 views
3

У меня есть этот кусок кода:C++ 11 <chrono> переполнения гарантирует

auto time_point_a = std::chrono::high_resolution_clock::now(); 
while (true) { 
    auto time_point_a = std::chrono::high_resolution_clock::now(); 
    auto counter_ms = std::chrono::duration_cast<std::chromo::milliseconds(time_point_a - time_point_b); 
    // more code 
std::count << counter_ms.count() << std::endl; 
} 

ли counter_ms.count() гарантированно всегда возвращает действительное значение? Есть ли вероятность, что count() выбрасывает? Что произойдет, если counter_ms превышает размер своего базового интегрального типа (я считаю, что он длинный)? Моя программа будет работать несколько дней подряд, и мне нужно знать, что произойдет, если/когда counter_ms становится слишком большим.

+0

Большая часть вопросов ответила в документации: ['std :: chrono :: duration'] (http://en.cppreference.com/w/cpp/chrono/duration). – m0nhawk

+1

Соответствующие биты: 'count()' не помечены 'noexcept',' Примечание: каждый из предопределенных типов длительности охватывает диапазон не менее ± 292 лет. ' – melak47

ответ

6

Действительно ли counter_ms.count() всегда возвращает допустимое значение?

counter_ms содержит один знак интегрального счета в миллисекундах. Функция-член .count() указана только для того, чтобы вернуть это знаковое целочисленное значение.

Есть ли вероятность, что счет() выбрасывает?

Эта функция-член не помечен noexcept по двум причинам:

  1. noexcept используется очень экономно в станд :: LIB.
  2. В общем, длительность может быть основана на арифметических эмуляторах, которые могут иметь конструктор метаданных.

В случае counter_ms, представление должно быть подписанным интегральным типом, который, конечно же, не может быть использован для создания копии.

Нет никаких шансов, что это бросит.

Что произойдет, если counter_ms превышает размер его базового интегрального типа (я считаю, что он длинный)?

Вы можете проверить, лежащий в основе интегрального типа с этой программой:

#include <chrono> 
#include <iostream> 
#include "type_name.h" 

int 
main() 
{ 
    std::cout << type_name<std::chrono::milliseconds::rep>() << '\n'; 
} 

Где "type_name.h" описывается here. Для меня эта программа выводит:

long long 

Стандартная спецификация говорит, что этот тип должен быть подписан интегральным типом, по крайней мере 45 бит. Это дает ему диапазон не менее +/- 557 лет. Вы можете найти фактический диапазон вашей реализации milliseconds с этой программой:

#include <chrono> 
#include <iostream> 

int 
main() 
{ 
    using days = std::chrono::duration 
     <int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>; 
    using years = std::chrono::duration 
     <int, std::ratio_multiply<std::ratio<146097, 400>, days::period>>; 

    std::cout << std::chrono::duration_cast<years> 
     (std::chrono::milliseconds::min()).count() << " years\n"; 
    std::cout << std::chrono::duration_cast<years> 
     (std::chrono::milliseconds::max()).count() << " years\n"; 
} 

, который для меня выходов:

-292277024 years 
292277024 years 

По совпадению, я один, который реализовал <chrono> реализации, я использую (libc++). И причина, по которой фактический диапазон намного превышает требуемый минимальный диапазон, заключается в том, что мне не удалось найти 45-битный подписанный интегральный тип и пришлось соглашаться на 64-битный подписанный интегральный тип.

Когда этот диапазон превышен, вы получите то же самое поведение, что и подписанное интегральное арифметическое переполнение (которое определено как неопределенное поведение).

+0

Можете ли вы объяснить вывод' -292277024' '' 292277024? 'лет? Похоже, что противоречит факту, что 45 бит в миллисекундах дает вам ~ 557,5 лет – AndyG

+0

@ AndyG: Done ... –

+0

Ну, не чувствую себя глупо! Конечно, 'long long' - 64 бит. Благодарю. Это, однако, заставляет меня спросить: «Почему странные минимальные биты в стандарте?» микросекунды - 55, часов 23, минуты - 29. Это кажется произвольным. – AndyG

Смежные вопросы