반응형

C++ 프로그래밍 32

C++ unique_ptr을 응용하여 자동으로 핸들을 닫는 클래스 만들기

C++을 사용하여 프로그램을 하다보면 핸들을 많이 다루게 됩니다. 특히 I/O 관련 작업을 할 때나 윈도우 API를 사용할 때 파일을 비롯한 각종 핸들(HANDLE)을 사용하게 됩니다. 이 때 다 사용한 핸들을 닫아주지 않으면 핸들 관련 누수(Leak)가 생기게 됩니다. 이럴 경우 unique_ptr을 이용하여 구간에서만 핸들을 사용하고 다 사용한 후에는 자동으로 핸들을 자동으로 닫게하면 위에서 말한 문제가 일어날 가능성이 적어지게 됩니다. 아래 예제 코드를 살펴보겠습니다. #include #include using namespace std; struct FileCloser { void operator()(FILE* file) const { if (file) { fclose(file); std::cout

C++ 프로그래밍 2024.04.15

C++ system_clock을 이용하여 64bit tick값 저장 및 로드 예제

게임의 아이템 등 여러 곳에서 데이터의 시간 값을 저장하고 로드합니다. 여기서는 system_clock을 이용하여 시간 값을 64bit 변수로 저장하고 로드하는 예제를 살펴보도록 하겠습니다. 참고로 변수 값은 보통 실무 프로젝트에서는 tick이라고 불리웁니다. 예제에서는 실제로 값을 저장하지는 않지만 long long 값인 tick 값을 64bit 변수 값으로 DB 등에 저장하고 로드하면 됩니다. #include #include using namespace std; using namespace chrono; int main(int argc, char* argv[]) { system_clock::time_point now = system_clock::now(); long long tick = now.tim..

C++ 프로그래밍 2022.03.28

C++ 람다를 활용하여 함수 내 중복 코드 줄이기

람다는 정말로 활용하면 할수록 유용한 기능인 듯합니다. 막상 활용하기 시작하니 람다 없던 시기의 코드에 비하여 코드의 양도 줄어들고 코드도 이해하기가 더 쉬워지는 듯 합니다. 이 글에서는 람다를 활용하여 함수내 중복 코드를 제거하는 예를 살펴보겠습니다. 아래 코드는 제가 작성한 코드로 실제 프로젝트에서 흔희 볼 수 있는 반복적인 코드입니다. 코드 내용은 중요하지 않으니 형태만 참고하시면 됩니다. switch (nSBCode) { case SB_LINEUP: pScrollBar->SetScrollPos(pScrollBar->GetScrollPos() - 1); if (chartUse_.test(IDX_CHART_SUB)) chartSub_->ScrollX(pScrollBar->GetScrollPos());..

C++ 프로그래밍 2022.03.23

C++ 람다 사용시 변수 캡처 주의점과 shared_ptr의 활용

C++의 람다는 근래에 많이 쓰이는 기술 중에 하나 입니다. 람다는 흔희 변수를 캡처하여 내부에서 많이 사용합니다. 이럴 때 생각해야 할 점이 변수를 참조로 캡처할 것인가 복사로 캡처할 것인가 하는 점입니다. 기본적으로 내부에서 캡처한 외부 변수의 값을 변경하고자 하거나 복사에 따른 오버헤드가 크다고 생각한다면 혹은 객체 내부에서 객체 함수 등을 참조해야 한다면 참조로 캡처를 사용하게 됩니다. 반대로 내부에서만 값을 변경 또는 사용하거나 복사에 따른 오버헤드가 크지 않으면 복사로 캡처하여 사용합니다. 람다는 참조로 캡처하여 사용할 때 주의점은 캡처한 변수가 람다를 다 사용할 때까지 메모리에 남아 있어야 한다는 것입니다. 간단한 아래와 같은 예를 하나 살펴보겠습니다. 참고로 이 예제는 실제로 일어날 수 있..

C++ 프로그래밍 2022.01.21

C++ string_view의 이해와 활용

string_view는 C++ 17에 추가된 클래스로 문자열에 대한 참조라고 볼 수 있습니다. 사용법은 string과 유사하며 장점은 string에 비하여 적은 메모리 사용량과 연산 성능에 대한 이점을 가지고 있습니다. 단점은 잘못된 사용시 임시 객체 사용에 따라 참조가 없어져 예상치 못한 에러가 발생할 가능성이 있으며 내부구조가 널로 종료하는 문자열을 참조하지 않는 관계로 널로 종료하는 문자열을 필요로하는 C API와 같은 함수에 사용할 수 없다는 점 등이 있습니다. 참고로 string_view는 가볍다는 장점을 바탕으로 몽고DB C++ 드라이버에서는 벌써 적절하게 사용하고 있습니다. 이 글에서는 string_view의 특성, 사용법, 장점 및 단점을 살펴보도록 하겠습니다. string_view 특성 ..

C++ 프로그래밍 2022.01.15

C++ 클래스 함수 간접 호출 : mem_fn, bind, bind_front

C++에서 클래스 함수를 간접적으로 호출할 수 있는 방식 중 mem_fn, bind, bind_front를 아래 예제로 살펴보도록 하겠습니다. #include #include using namespace std; class test_class_fn { public: int add(int a, int b) { return a + b; } auto get_func_mem_fn() { return mem_fn(&test_class_fn::add); } function get_func_bind() { return bind(&test_class_fn::add, this, std::placeholders::_1, std::placeholders::_2); } function get_func_bind_front() ..

C++ 프로그래밍 2021.12.11

C++ 전역 객체 혹은 정적 객체 간의 생성 및 소멸 순서 문제

C++에서 전역 객체 혹은 정적 객체들의 생성과 소멸 순서는 따로 규칙이 정해져 있지 않습니다. C++ 전역 혹은 정적 객체 생성에 관해서 정해져 있는 것은 초기화 이전에 0으로 초기화 된다는 것 뿐입니다. 그 외에 메인의 첫 문장 실행 전에 지역 변수가 아닌 정적 변수가 초기화될 것인지 여부는 컴파일 구현에 따라 틀립니다. 이런 세세한 것을 알아야 하는 이유는 전역 혹은 정적 객체간에 직접적 혹은 간접적으로 참조를 하는 경우에 문제가 생길 수 있기 때문입니다. 한 예로 전역 변수 A가 정적 변수 B를 호출하는데 생성 및 초기화 순서에 따라 전역 변수 A는 초기화 되지 않는 정적 변수 B를 호출할 수 있습니다. 이런 경우 프로그램이 멈추거나 잘못된 값을 가지는 알 수 없는 상황이 발생하게 됩니다. 또 다..

C++ 프로그래밍 2021.12.09

C++ using namespace를 헤더 파일에 사용하지 말자

using namespace는 특정 네임스페이스의 클래스들을 네임스페이스 참조 없이 사용하기 위하여 흔히 사용하는 문법입니다. 흔한 예로는 STL을 사용하기 위하여 사용하는 using namespace std;와 같은 것이 있습니다. 네임스페이스를 생략하는 편의성 때문에 헤더에 using namespace를 사용하니 아래와 같은 문제가 발생하였습니다. 현재 개발 중인 프로젝트에서 사용하는 라이브러리들이 STL, Boost, MongoCXX, Cybos API등인데 같은 클래스이름 때문에 충돌이 발생하였습니다. 헤더 파일에서야 원인을 파악하고 클래스 앞에 네임스페이스를 넣어줘서 충돌을 막아줄 수 있었습니다. 그런데 cpp파일에서는 using namespace 구문이 있는 헤더가 포함되니 포함 순서에 따라서..

C++ 프로그래밍 2021.12.01

C++ 람다에서 참조 값과 복사 값 동시에 사용하기

C++ 람다는 C++ 특성상 복사와 참조 그리고 객체의 생명주기 등을 고려해야 메모리 관련 버그가 없습니다. 람다에서 참조만 사용할 경우 프로그램에 따라서 참조하는 값이 메모리에서 해제되면 메모리 관련 버그가 발생하게 됩니다. 이럴 경우 복사를 같이 사용해야 합니다. 해당 설명에 대한 아래 예를 살펴보겠습니다. 아래 코드는 해당 상황을 보여주기 위한 예제인 관계로 현실적인 사용과는 조금 다를 수 있으니 참고 바랍니다. #include #include #include using namespace std; struct std_15_sub { public: int value = 1; }; class std_15A { private: void print_value(int value) { cout value]의 ..

C++ 프로그래밍 2021.11.29

std::chrono::steady_clock 관련 종합 예제

std::chrono::steady_clock을 사용할 일이 있어서 이리 저리 조사를 하며 만들어본 예제입니다. 예제에는 지나간 시간 체크, 시간 차 duration에 시간 더하기, 현재 구한 시간에 시간 더하기, duration과 long long간의 형변환, 시간차를 나타내는 duration 시간 이쁘게 보여주기 등등이 포함되어 있습니다. 예제 소스는 아래와 같습니다. #include #include #include #include using namespace std; int main(int argc, char* argv[]) { // 예제 #1: 지나간 시간을 체크합니다. auto now1 = std::chrono::steady_clock::now(); this_thread::sleep_for(st..

C++ 프로그래밍 2021.11.22

동적 라이브러리(DLL)를 사용할 것인가? 아니면 정적 라이브러리(LIB)를 사용할 것인가?

일정 규모 이상의 프로그램을 만들다보면 공통적으로 참조하는 공통 라이브러리를 만들고 여러 프로그램에서 참조하게 하는 경우가 종종 있습니다. 공통 라이브러리는 프로그램에 내용이 포함되는 정적 라이브러리와 DLL, SO등의 별도 확장자로 필요에 따라 로딩되어 참조되는 동적 라이브러리가 있습니다. C++이나 기타 언어의 서적을 보게 되면 실행 파일이 참조하는 라이브러리로 보통은 동적 라이브러리를 많이 추천합니다. 동적 라이브러리의 장점은 아래와 같습니다. 첫째로 여러 프로그램이 참조하더라도 라이브러리 사용 메모리는 하나의 프로그램의 사용에 필요한 만큼만 필요합니다. 덕분에 메모리는 여러개의 프로그램에서 참조하더라도 (사용 프로그램 수 N개 - 1) * 사용 메모리 크기 만큼 절약하게 됩니다. 둘째로 라이브러리..

C++ 프로그래밍 2021.11.18

C++ chrono system_clock과 steady_clock의 이해 및 차이점

C++ chrono 라이브러리에는 기본적으로 system_clock과 steady_clock 두 개의 시간 측정 클래스가 존재합니다. 두 클래스의 기본적인 개념은 아래와 같습니다. system_clock은 전통적인 유닉스 타임으로 1970 1월 1일 목요일 0시 0분 0초 이후로 흘러간 시간을 나타냅니다. 그에 반하여 steady_clock은 마지막 부팅 이후로 흘러간 시간을 나타냅니다. 흔히 하는 이야기로 시계를 표현하기 위해서는 system_clock을, 초시계를 표현하기 위해서는 steady_clock을 사용해야 합니다. 그 이유는 system_clock과 같은 경우 OS 시간 동기화 등에 의하여 시간 측정 중에 시간 값이 변할 수 있기 때문인데 반하여 steady_clock은 그럴 가능성이 없기 ..

C++ 프로그래밍 2021.11.10

C/C++ __FUNCTION__, __FILE__의 유니코드 버전

유니코드를 출력하는 wcout이나 유니코드를 인자로 요구하는 함수와 같은 경우 __FUNCTION__, __FILE__이 제대로 출력되지 않습니다. 구글링 해보면 #define을 이용하여 새롭게 정의하여 출력하는 방식이 나와 있습니다. 처음에는 그렇게 사용했는데 비주얼스튜디오와 같은 경우(현재 2019 이용) 해당 __FUNCTION__, __FILE__의 유니코드 버전인 __FUNCTIONW__, __FILEW__을 corecrt.h에서 정의하고 있었습니다. 어느 버전부터 지원하는 지는 모르겠지만 최신 비주얼 스튜디오를 사용하신다면 그냥 __FUNCTION__, __FILE__을 유니코드로 사용하여야 한다면 __FUNCTIONW__, __FILEW__을 사용하시면 됩니다.

C++ 프로그래밍 2021.11.01

C++ invoke_result: return type 알아내기

invoke_result는 C++ 17부터 추가된 함수의 리턴 타입을 알아내는데 사용되는 함수 입니다. 기존에는 C++ 11에 추가된 result_of가 사용되었는데 C++ 20에서 삭제된 관계로 더 이상 result_of는 사용할 수 없습니다. 해당 함수는 템플릿을 프로그래밍을 할 때 사용할 수 있는 함수인 관계로 일반적인 프로그래밍에는 별로 사용되지 않을 듯 보입니다. 사용법은 invoke_result::type 입니다. 비주얼 스튜디오에서 제대로된 인자를 넣지 않을 경우 인텔리센스에서 멤버로 type이 나오지 않습니다. 아래 예제는 std::result_of, std::invoke_result(https://en.cppreference.com/w/cpp/types/result_of)을 응용하여 작성..

C++ 프로그래밍 2021.10.31
반응형