전체 글
-
Lambda(람다)Modern C++/Lambda 2020. 7. 15. 02:52
1. Lamda Syntax Overview 람다는 클로져(closure)를 만들어내는 표현식(expression)으로 보통 람다 표현식 또는 람다 함수라고 부른다. 클로져는 범위 내 변수를 캡쳐 할 수 있는 이름없는 함수 객체이다. [] (int x, int y) -> int {return x + y; } //후행 반환 타입은 해당 람다의 본문의 반환 값을 통해서 추론 가능해 생략 가능하다. [] (int x, int y) { return x + y; } []() { std::cout int { return x * y; } captures : 외부 변수를 람다의 본문(body)에서 사용할 있게 캡쳐할 변수 목록 tparams : 템플릿 가변 인자 리스트 params : 함수 인자 목록 specifier..
-
스마트 포인터 참조 가이드(Smart Pointer Referece Guide)Modern C++/Smart Pointer 2020. 7. 12. 20:11
1. new를 이용한 동적 객체 생성은 피하되 필요한 경우 스마트 포인터를 사용하라. 스택을 사용하고 할당연산자나 이동/복사 연산을 사용하는게 객체의 수명 관리가 편해 코드가 어떻게 동작하는 지 예측하기 편하다. 동적 할당은 메모리를 힙에 할당하는 데 비용이 드는 것 뿐 만 아니라 메모리의 위치가 연속적이지 않아 컴파일러가 코드의 최적화를 수행하는 데 걸림돌이 되기도 한다. 메모리 할당은 필요할 때만 해야하고 new/delete를 직접 사용하지 않고 스마트 포인터를 사용하면 메모리를 직접 관리해야 하는 부담을 줄일 수 있다. 2. 스마트 포인터 선택 시 가장 먼저 std::unique_ptr 사용을 고려하라. 동적 메모리 할당이 필요한 경우 우선적으로 std::unique_ptr 사용을 고려한다. std..
-
2. std::shared_ptr 과 std::weak_ptrModern C++/Smart Pointer 2020. 7. 12. 17:07
std::shared_ptr 동적 할당된 객체의 소유권을 공유할 때 std::shared_ptr를 이용해 메모리를 관리한다. 메모리 해제 시점은 동적 객체를 가리키는 모든 공유 포인터가 더 이상 해당 객체를 가리키지 않을 때로 더 이상 공유 포인터가 가리키는 객체의 수명에 대해 신경 쓸 필요가 없어진다. 이렇게 메모리가 해제되는 시점은 원자적 참조 횟수(atomic reference count)를 통해 공유 포인터 생성 시 카운트를 증가시키고, 소멸 시 카운트를 감소시킨다. 복사 배정 연산자의 경우 증가와 감소가 모두 일어난다. 참조 횟수는 제어 블록(control block)에서 관리하며 공유 포인터의 대략적인 구조는 아래와 같다. 위와 같이 공유 포인터는 객체를 가리키는 포인터와 별개로 제어블록을 가..
-
Boost를 이용한 객체 직렬화(Object Serialization)C++ with Boost 2020. 7. 11. 16:12
객체 직렬화 객체 직렬화는 객체를 전송가능한 형태의 연속적인 데이터로 변형하는 것으로 파일로 저장하거나 전송할 때 사용된다. 객체를 연속적인 데이터로 변환하는 과정을 직렬화 연속적인 데이터를 객체로 변환하는 과정을 역직렬화라고 한다. 자바나 C# 은 객체 직렬화를 언어 자체에서 지원하지만 C++은 이를 지원하지 않는다.여기서는 boost의 serialization 컴포넌트를 사용해 직렬화를 구현하는 방법을 살펴본다. Boost 의 객체 직렬화 boost::text_oarchive는 객체를 받아 직렬화를 수행한 후 출력 스트림 객체에 전달한다. 반대로 text_iarchive 는 입력 스트림으로 직렬화된 데이터를 받아 객체로 변환한다. 부스트의 텍스트 입출력 아카이브(text_oarchive, text_i..
-
macOS에서 부스트(Boost)라이브러리 사용하기C++ with Boost 2020. 7. 10. 15:47
Home brew(홈 브루) macOS용 패키지 관리자로 터미널에서 명령을 통해 쉽게 필요한 프로그램을 설치, 삭제, 업데이트 할 수 있다. 이는 RedHat 계열의 리눅스에서 사용하는 yum 이나 Ubuntu 계열의 리눅스에서 사용하는 apt-get과 같다고 생각하면 된다. Home brew 설치 $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" Home brew 업데이트 $ brew update Home brew 삭제 $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)" Ho..
-
1. std::unique_ptrModern C++/Smart Pointer 2020. 7. 2. 18:39
C++ 메모리 관리 C++에서 생 포인터(raw pointer)를 관리하기는 쉽지 않다. 자바는 가비지 콜렉터가 이를 수행하지만 C++같은 경우 사용자가 직접 메모리를 관리해야 한다. 잘못된 메모리 관리는 메모리 릭이 발생하거나 더블 프리 문제로 프로그램이 예외를 던지고 프로그램이 종료하기도 한다. 여기서 생 포인터를 사용하기 어려운 이유를 살펴 보기로 하자. struct Data { uint8_t *data_; size_t length_; }; 여기서 data_는 하나의 객체를 가리키는 포인터인지 배열을 가리키는 포인터인지 코드 자체로는 구별할 수 없다. 생성자에는 uint8_t 형 배열 포인터와 해당 배열의 크기를 받는 생성자와 소멸자를 추가해보자. struct Data { Data(const uin..
-
5. C++11 객체 생성 규칙 Rule of FiveModern C++/Move Semantics 2020. 7. 1. 23:55
C++11 이전 컴파일러가 생성하는 특수 멤버 함수 C++11 이전 컴파일러는 기본 생성자(Basic Constructor), 소멸자(Destructor) , 복사 생성자(Copy Constructor), 복사 할당자(Copy Assignment)를 필요한 경우 자동으로 생성한다. 이는 컴파일 도중 해당 연산을 사용하는 코드가 있는 경우 컴파일러에 의해 암묵적으로 public inline으로 자동으로 생성 된다. class Foo { }; Foo f0; //기본 생성자 생성 Foo f1 = f0; //복사 생성자 생성 Foo f1(f0); //Foo f1 = f0 와 동일 Foo f2; Foo f2 = f0; // 할당 연산자 생성 위의 Foo 클래스는 사용자가 아무것도 정의하지 않았지만 컴파일러가 Fo..
-
4. 이동가능 객체(Movable Type)Modern C++/Move Semantics 2020. 6. 30. 01:15
클래스를 이동 가능하게 만들면 많은 장점들이 있고 이동 가능한 사용자 정의 타입은 표준 라이브러리 유틸과도 잘 동작한다. 이동 연산을 지원하는 클래스를 만드는 경우 코드의 성능, 안정성이나 구현 할 수 있는 방식이 증가한다. 이동 가능한 사용자 타입을 정의하게 되면 표준 라이브리를 사용하는 중에도 이동 연산에 대한 이점을 얻을 수 가 있다. C++11 이전에 컴파일러는 기본 생성자, 소멸자, 복사 생성자, 복사 할당 연산자를 자동으로 추가해 주었는데, C++11 이 후는 여기에 이동 생성자와 이동 할당 연산자가 추가되었다. 여기서는 유리수를 나타내는 Rational 클래스를 통해서 이동 연산이 추가되었을 때 어떤 장점이 있는지 살펴본다. #pragma once #include class Rational ..