C++ duration | "시간 간격" 가이드
이 글의 핵심
C++ duration에 대한 실전 가이드입니다.
들어가며
**std::chrono::duration**은 시간 간격을 표현하는 타입입니다. 타입 안전하고, 단위 변환이 명확하며, 시간 연산을 지원합니다.
1. duration 기본
기본 사용
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
// 시간 간격 생성: duration 타입
// std::chrono::seconds: 초 단위 duration
seconds sec(10); // 10초
// std::chrono::milliseconds: 밀리초 단위 duration
milliseconds ms(10000); // 10000밀리초 = 10초
// std::chrono::minutes: 분 단위 duration
minutes min(1); // 1분 = 60초
// std::chrono::hours: 시간 단위 duration
hours hr(1); // 1시간 = 60분 = 3600초
// 값 얻기: count() 메서드로 숫자 값 추출
std::cout << "초: " << sec.count() << std::endl; // 10
std::cout << "밀리초: " << ms.count() << std::endl; // 10000
return 0;
}
표준 duration 타입
#include <chrono>
// C++11 표준 단위
std::chrono::hours h(1);
std::chrono::minutes m(60);
std::chrono::seconds s(3600);
std::chrono::milliseconds ms(3600000);
std::chrono::microseconds us(3600000000);
std::chrono::nanoseconds ns(3600000000000);
// 모두 1시간을 표현
2. 시간 변환
암시적 변환 (상위 → 하위)
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
seconds s(10); // 10초
// ✅ 상위 → 하위 (암시적 변환 가능)
// 큰 단위 → 작은 단위: 정보 손실 없음
// seconds → milliseconds: 10초 = 10000밀리초
milliseconds ms = s; // 10000ms (자동 변환)
// seconds → microseconds: 10초 = 10000000마이크로초
microseconds us = s; // 10000000us (자동 변환)
std::cout << "밀리초: " << ms.count() << std::endl; // 10000
std::cout << "마이크로초: " << us.count() << std::endl; // 10000000
return 0;
}
명시적 변환 (하위 → 상위)
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
milliseconds ms(1500); // 1500밀리초 = 1.5초
// ❌ 하위 → 상위 (암시적 불가)
// 작은 단위 → 큰 단위: 정보 손실 가능 (소수점 버림)
// seconds s = ms; // 컴파일 에러: 명시적 변환 필요
// ✅ duration_cast (명시적 변환)
// duration_cast<seconds>: 밀리초를 초로 변환
// 1500ms → 1s (500ms 버림, 절삭)
seconds s = duration_cast<seconds>(ms); // 1s (절삭)
std::cout << "초: " << s.count() << std::endl; // 1
return 0;
}
C++17 반올림 함수
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
milliseconds ms(1500); // 1500밀리초 = 1.5초
// duration_cast: 절삭 (소수점 버림)
// 1.5초 → 1초 (0.5초 버림)
auto s1 = duration_cast<seconds>(ms);
std::cout << "절삭: " << s1.count() << "s" << std::endl; // 1s
// round: 반올림 (C++17)
// 1.5초 → 2초 (0.5 이상이므로 올림)
auto s2 = round<seconds>(ms);
std::cout << "반올림: " << s2.count() << "s" << std::endl; // 2s
// ceil: 올림 (C++17)
// 1.5초 → 2초 (무조건 올림)
auto s3 = ceil<seconds>(ms);
std::cout << "올림: " << s3.count() << "s" << std::endl; // 2s
// floor: 내림 (C++17)
// 1.5초 → 1초 (무조건 내림, duration_cast와 동일)
auto s4 = floor<seconds>(ms);
std::cout << "내림: " << s4.count() << "s" << std::endl; // 1s
return 0;
}
3. 시간 연산
산술 연산
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
seconds s1(10);
seconds s2(5);
// 덧셈
auto sum = s1 + s2;
std::cout << "합: " << sum.count() << "s" << std::endl; // 15s
// 뺄셈
auto diff = s1 - s2;
std::cout << "차: " << diff.count() << "s" << std::endl; // 5s
// 곱셈
auto mul = s1 * 2;
std::cout << "곱: " << mul.count() << "s" << std::endl; // 20s
// 나눗셈
auto div = s1 / 2;
std::cout << "나눔: " << div.count() << "s" << std::endl; // 5s
// 나머지
auto mod = s1 % s2;
std::cout << "나머지: " << mod.count() << "s" << std::endl; // 0s
return 0;
}
비교 연산
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
seconds s1(10);
seconds s2(5);
milliseconds ms(10000);
std::cout << std::boolalpha;
std::cout << "s1 > s2: " << (s1 > s2) << std::endl; // true
std::cout << "s1 == ms: " << (s1 == ms) << std::endl; // true (단위 다름)
return 0;
}
4. duration 리터럴 (C++14)
리터럴 사용
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono_literals;
// 리터럴로 duration 생성
auto d1 = 10s; // seconds
auto d2 = 500ms; // milliseconds
auto d3 = 100us; // microseconds
auto d4 = 100ns; // nanoseconds
auto d5 = 1min; // minutes
auto d6 = 2h; // hours
// 조합
auto total = 1h + 30min + 45s + 500ms;
auto total_ms = std::chrono::duration_cast<std::chrono::milliseconds>(total);
std::cout << "총 시간: " << total_ms.count() << "ms" << std::endl; // 5445500ms
return 0;
}
5. 자주 발생하는 문제
문제 1: 정밀도 손실
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
milliseconds ms(1500);
// ❌ duration_cast: 절삭 (500ms 손실)
seconds s1 = duration_cast<seconds>(ms);
std::cout << "절삭: " << s1.count() << "s" << std::endl; // 1s
// ✅ round: 반올림
seconds s2 = round<seconds>(ms);
std::cout << "반올림: " << s2.count() << "s" << std::endl; // 2s
return 0;
}
문제 2: 타입 불일치
#include <chrono>
#include <iostream>
void waitFor(std::chrono::seconds s) {
std::cout << s.count() << "초 대기" << std::endl;
}
int main() {
// ❌ 타입 불일치
// waitFor(10); // 컴파일 에러
// ✅ 명시적 생성
waitFor(std::chrono::seconds(10));
// ✅ 리터럴 (C++14)
using namespace std::chrono_literals;
waitFor(10s);
return 0;
}
문제 3: 음수 duration
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
seconds s1(5);
seconds s2(10);
// 음수 duration
auto diff = s1 - s2; // -5s
std::cout << "차이: " << diff.count() << "s" << std::endl; // -5
// 절대값
auto abs_diff = (diff < seconds::zero()) ? -diff : diff;
std::cout << "절대값: " << abs_diff.count() << "s" << std::endl; // 5
return 0;
}
문제 4: 0 duration
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
// 0 duration
seconds s = seconds::zero();
milliseconds ms = milliseconds::zero();
std::cout << std::boolalpha;
std::cout << "s == 0: " << (s == seconds::zero()) << std::endl; // true
return 0;
}
6. 실전 예제: 타이머 유틸리티
#include <chrono>
#include <thread>
#include <iostream>
class Timer {
using Clock = std::chrono::steady_clock;
using TimePoint = std::chrono::time_point<Clock>;
TimePoint start;
public:
Timer() : start(Clock::now()) {}
// 경과 시간 (밀리초)
long long elapsedMs() const {
auto now = Clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
return duration.count();
}
// 경과 시간 (마이크로초)
long long elapsedUs() const {
auto now = Clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(now - start);
return duration.count();
}
// 재시작
void reset() {
start = Clock::now();
}
};
int main() {
Timer timer;
// 작업 1
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "작업 1 완료: " << timer.elapsedMs() << "ms" << std::endl;
// 작업 2
std::this_thread::sleep_for(std::chrono::milliseconds(200));
std::cout << "작업 2 완료: " << timer.elapsedMs() << "ms" << std::endl;
// 재시작
timer.reset();
// 작업 3
std::this_thread::sleep_for(std::chrono::milliseconds(150));
std::cout << "작업 3 완료: " << timer.elapsedMs() << "ms" << std::endl;
return 0;
}
출력:
작업 1 완료: 100ms
작업 2 완료: 300ms
작업 3 완료: 150ms
정리
핵심 요약
- duration: 시간 간격 표현
- count(): 값 얻기
- 상위→하위: 암시적 변환
- 하위→상위:
duration_cast필요 - 연산: +, -, *, /, % 지원
- 리터럴:
10s,500ms(C++14)
duration 변환 규칙
| 변환 | 방법 | 예시 |
|---|---|---|
| 상위 → 하위 | 암시적 | milliseconds ms = seconds(10); |
| 하위 → 상위 | duration_cast | seconds s = duration_cast<seconds>(ms); |
| 반올림 | round (C++17) | seconds s = round<seconds>(ms); |
| 올림 | ceil (C++17) | seconds s = ceil<seconds>(ms); |
| 내림 | floor (C++17) | seconds s = floor<seconds>(ms); |
실전 팁
사용 원칙:
- 상위→하위는 암시적
- 하위→상위는
duration_cast - 반올림은
round(C++17) - 리터럴 사용 (
10s,500ms)
성능:
duration_cast는 컴파일 타임- 연산은 정수 연산과 동일
- 타입 안전으로 버그 방지
- 리터럴로 가독성 향상
주의사항:
duration_cast는 절삭 (정밀도 손실)- 음수 duration 가능
zero(),min(),max()특수 값- 단위 불일치 주의
다음 단계
- C++ Time Point
- C++ Chrono
- C++ Timer Utilities
관련 글
- C++ Chrono 상세 가이드 |
- C++ Chrono 완벽 가이드 |
- C++ Chrono Literals |
- C++ ratio |
- C++ steady_clock |