728x90
반응형

Program Language 197

[C++] Class Template

데이터 멤버 보통 클래스의 경우 클래스 템플릿에는 모든 유형의 데이터 멤버가 포함될 수 있다. non-static 멤버는 해당 저의 또는 생성자에서 초기화할 수 있다. template struct X { int m1 = 7; T m2; X(const T& x) :m2{x} { } }; X xi {9}; X xs {"Rapperswil"}; non-static 데이터 멤버는 const일 수 있지만 constexpr일 수는 없다. 멤버 함수 보통 클래스는 클래스 템플릿의 non-static 멤버 함수를 클래스 내부 또는 외부에서 정의할 수 있다. template struct X { void mf1() { /* ... */ } // defined in-class void mf2(); }; template vo..

[C++] Simple String 템플릿

특정 문자에 대한 의존도를 최소화하면서 '문자열'의 개념을 표현하고자 한다. 예를 들어 부호 있는 문자, 부호 없는 문자, 중국어, 그리스어 등등 다양한 context에 유용하게 사용한다. 문자열의 정의는 문자를 복사할 수 있다는 사실에 의존하고 다른 것은 거의 없다. template class String { public: String(); explicit String(const C∗); String(const String&); String operator=(const String&); // ... C& operator[](int n) { return ptr[n]; } // unchecked element access String& operator+=(C c); // add c at end // .....

[C++] std::chrono로 시간 측정하기

std::chrono가 제공되면서 시간 연산이 더욱 쉬워졌다. 기존에 정밀한 단위의 시간을 측정하려면 OS에서 제공하는 API를 사용해야 했는데 이제는 번거로움이 사라졌다. #include #include using namespace std; int main() { std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); for (int i = 0; i < 10000000; i++) std::sqrt(10000000000); std::chrono::duration sec = std::chrono::system_clock::now() - start; std::cout

[C++] unique_lock, lock_guard

unique_lock과 lock_guard의 차이점은 lock을 걸 수 있는 시점이다. 둘 다 소멸 시점에 lock이 걸려 있다면 unlock을 수행한다. lock_guarud는 lock과 unlock 사이에서 lock과 unlock을 할 수 없지만 unique_lock은 소멸하기 전에 unlock과 lock을 걸 수 있다. unique_lock은 lock_guard에 기능이 추가된 버전이라고 생각하면 된다. 이러한 lock 유틸리티 객체를 사용하는 것은 프로그래머가 unlock 코드에 신경 쓰지 않아도 되게 해 준다. 아래와 같이 사용하면 된다. std::mutex m_mutex; std::lock_guard lock(m_mutex); std::unique_lock lock(m_mutex);

[C++] 함수 delete

함수를 '삭제'할 수 있다. 즉, 함수가 존재하지 않는다고 명시하여 그것을 사용하려고 시도하는 것은 오류다. 가장 확실한 용도는 기본 설정이 아닌 기능을 제거하는 것이다. 예를 들어, 베이스로 사용되는 클래스의 복사는 슬라이싱으로 이어지기 때문에 이를 방지하고자 하는 것이 일반적이다. class Base { // ... Base& operator=(const Base&) = delete;// disallow copying Base(const Base&) = delete; Base& operator=(Base&&) = delete; // disallow moving Base(Base&&) = delete; }; Base x1; Base x2 {x1}; // error : no copy constr ucto..

[C++] static 멤버 초기화

static 클래스 멤버는 클래스의 각 객체의 일부가 아니라 정적으로 할당된다. 일반적으로 static 멤버 선언은 클래스 외부의 정의에 대한 선언 역할을 한다. class Node { // ... static int node_count; // declaration }; int Node::node_count = 0; // definition 하지만 몇 가지 간단한 특별한 경우에는 클래스 선언에서 static 멤버를 조기화할 수 있다. static 멤버는 정수 또는 열거형 형성의 const이거나 리터럴 형식의 constexpr이어야 하고 intiailizer는 상수식이어야 한다. class Curious { public: static const int c1 = 7; // OK static int c2 = ..

[C++] initializer-list 생성자

std::initializer_list 유형의 단일 인수를 사용하는 생성자를 초기화 목록 생성자라고 한다. 초기화 목록 생성자는 {} 목록을 초기화 값을 사용하여 객체를 생성하는 데 사용된다. 표준 라이브러리 컨테이너(예:벡터 및 맵)에는 초기화 목록 생성자, 할당 등이 있다. vector v = { 1, 2, 3.456, 99.99 }; list languages = { {"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"} }; map years = { { {"Maurice","Vincent", "Wilkes"},{1913, 1945, 1951, 1967, 2000} }, { {"Mar tin", "Richards"} {1982, 2003, 2007}..

[C++] 클래스 static 멤버

공개적으로 액세스 할 수 있는 전역 변수를 사용하지 않고도 편리함을 얻을 수 있다. 클래스의 일부이지만 해당 클래스의 객체의 일부가 아닌 변수를 static 멤버라고 한다. 일반 non-static 멤버와 같이 객체 하나의 복사본이 아니라 정확히 하나의 static 멤버 복사본이 있다. 마찬가지로 클래스의 멤버에 액세스해야 하지만 특정 객체에 대해 호출할 필요가 없는 함수를 static 멤버 함수라고 한다. 다음은 전역에 대한 의존으로 인한 문제없이 Date에 대한 기본 생성자 값의 의미 체계를 유지하는 설계다. class Date { int d, m, y; static Date default_date; public: Date(int dd =0, int mm =0, int yy =0); // ... st..

[C++] 클래스 가변성(mutability)

명명된 객체를 상수나 변수로 정의할 수 있다. 즉, 이름은 변경할 수 없거나 변경할 수 있는 보유하는 객체를 참조할 수 있다. 변경할 수 없는 객체를 체계적으로 사용하면 코드를 더 이해하기 쉽게 만들고 더 많은 오류를 조기에 발견하고 때로는 성능을 개선할 수 있다. 특히 불변성은 다중 스레드 프로그램에서 가장 유용한 속성이다. 기본 제공 유형의 단순 상수 정의를 넘어서 유용하려면 다음을 수행할 수 있어야 한다. 사용자 정의 유형의 const 객체에서 작동하는 함수를 정의한다. const T& 인수를 사용하는 함수를 의미하는 독립 함수의 경우. 클래스의 경우 const 객체에서 작동하는 멤버 함수를 정의할 수 있어야 함을 의미한다. const 멤버 함수 Date 값을 조사하는 방법을 제공하기 위해서 일, ..

[C++] 클래스 explicit 생성자

기본적으로 단일 인수에 의해 호출된 생성자는 인수 유형에서 해당 유형으로 암시적 변환으로 작동한다. complex d {1}; // d=={1,0} (§5.6.2) 이러한 암시적 변환은 매우 유용할 수 있다. complex는 한 예다. 허수부를 생략하면 실수 축에 복소수가 표시된다. 그것이 바로 수학적 요구다. 그러나 많은 경우 이러한 변환은 혼란과 오류의 중요한 원인이 될 수 있다. Date를 예로 보자. void my_fct(Date d); void f() { Date d {15}; // plausible: x becomes {15,today.m,today.y} // ... my_fct(15); // obscure d = 15; // obscure // ... } 이것은 모호하다. 코드의 복잡성과는 ..

[C++] namespace를 이용한 version 관리

많은 종류의 인터페이스에 대한 가장 어려운 테스트는 일연의 새 릴리즈(버전)에 대처하는 것이다. ISO C++ 표준 헤더와 같이 널리 사용되는 인터페이스를 고려해 보자. 사용자가 정확히 하나의 특정 버전을 볼 수 있도록 간단하고 명확하게 두 버전 중에서 선택하는 방법이 있다. 이것을 인라인 네임스페이스라고 한다. namespace Popular { inline namespace V3_2 { // V3_2 provides the default meaning of Popular double f(double); int f(int); template class C { /* ... */ }; } namespace V3_0 { // ... } namespace V2_4_2 { double f(double); tem..

[C++] Catching Exception

void f() { try { throw E{}; } catch(H) { // when do we get here? } } 핸들러는 호출된다. H가 E와 같은 유형인 경우 H가 E의 명확한 공개 기반인 경우 H와 E가 포인터 유형이고 [1] 또는 [2]가 참조하는 유형에 대해 유지되는 경우 H가 참조이고 [1] 또는 [2]가 H가 참조하는 유형에 대해 유지되는 경우 또한 예외를 잡는 데 사용되는 유형에 const를 추가할 수 있다. 이것은 우리가 잡을 수 있는 예외 집합을 변경하지 않는다. catch 된 예외를 수정하지 못하도록 제한할 뿐이다. 참조로 예외를 catch 할 가능성에 유의하자. 예외 유형은 종종 그들이 나타내는 오류 종류 간의 관계를 반영하기 위해 클래스 계층의 일부로 정의된다. 예외 클래..

[C++] throwing exception

복사하거나 이동할 수 있는 모든 유형의 예외를 throw 할 수 있다. class No_copy { No_copy(const No_copy&) = delete; // prohibit copying (§17.6.4) }; class My_error { // ... }; void f(int n) { switch (n) { case 0: throw My_error{}; // OK case 1: throw No_copy{}; // error : can’t copy a No_copy case 2: throw My_error; // error : My_error is a type, rather than an object } } catch 된 exception object는 원칙적으로 throw 된 객체의 복사본이다..

[C++] Finally

소멸자를 사용하여 리소스를 클래스의 객체로 표현하는데 필요한 규율은 일부를 귀찮게 한다. 계속해서 사람들은 예외가 발생한 후 정리할 임의의 코드를 작성하기 위해 finally를 만들었다. 이러한 기술은 애드혹(adhoc)이기 때문에 일반적으로 RAII보다 좋지 않지만 원한다면 RAII는 애드혹을 제공할 수 있다. 먼저 소멸자에서 임의의 작업을 실행할 클래스를 정의한다. template struct Final_action { Final_action(F f): clean{f} {} ˜Final_action() { clean(); } F clean; }; finally action은 생성자에 대한 인수로 제공된다. 다음으로, 액션의 유형을 편리하게 추론할 수 있는 함수를 정의한다. template Final_..

[C++] 리소스 관리

함수가 리소스를 획득할 때(즉, 파일을 열고, 여유 저장소에서 일부 메모리를 할당하고, 뮤텍스를 획득하는 등) 리소스가 적절하게 해제되는 시스템의 향후 실행을 위해 종종 필수적이다. 종종 적절한 릴리즈는 호출자에게 반환하기 전에 이를 획득한 함수가 릴리스하도록 할 수 있다. void use_file(const char∗ fn) // naive code { FILE∗ f = fopen(fn,"r"); // ... use f ... fclose(f); } fopen() 호출 후 및 fclose() 호출 전에 문제가 발생하면 예외로 인해 fclose()가 호출되지 않고 use_file()이 종료될 수 있다는 것을 알아차릴 때까지는 그럴듯해 보인다. 예외 처리를 지원하지 않는 언어에서도 똑같은 문제가 발생할 수..

[C++] 미리 정의된 매크로

몇 가지 매크로는 컴파일러에서 미리 정의한다. __cplusplus. C++컴파일에 정의되어 있다.(C컴파일에는 없음) __DATE__. "yyyy:mm:dd" 형식의 날짜 __TIME__. "hh:mm:ss"형식의 시간 __FILE__. 현재 소스 파일의 이름 __LINE__. 현재 소스 파일 내의 소스 라인 번호 __FUNC__. 현재 함수의 이름을 지정하는 구현 정의 구현 정의된 C-스타일 문자열 __STDC_HOSTED__. 구현이 호스팅 되는 경우 1 그렇지 않으면 0. 또한 구현 시 몇 가지 매크로가 조건부로 정의됨 __STDC__. C 컴파일에서 정의됨(C++ 컴파일에서는 없음) __STDC_MB_MIGHT_NEQ_WC__. wchar_t에 대한 인코딩에서 기본 문자 집합의 구성원이 일반 문..

[C++] constexpr 함수

일반적으로 함수는 compile-time에서 평가할 수 없으므로 상수 표현식에서 호출할 수 없다. constexpr함수를 지정함으로써 상수 표현식이 인수로 주어지면 상수 표현식에서 사용할 수 있기를 원한다는 것을 나타낸다. constexpr int fac(int n) { return (n>1) ? n∗fac(n−1) : 1; } constexpr int f9 = fac(9); // must be evaluated at compile time constexpr이 함수 정의에서 사용될 때, "상수 표현식이 인수로 주어지면 상수 표현식을 사용할 수 있어야 한다"라는 의미다. 객체 정의에서 사용하면, compile-time에 intiailizer를 평가한다는 의미다. void f(int n) { int f5 =..

728x90
반응형