shared_ptr의 특징 C 와 C++ 를 프로그래밍을 하다보면 가장 어려운 점이 바로 메모리 관리이다. 이전 항목에서 배운 unique_ptr 를 사용하면 자동으로 메모리를 해주기는 하지만 여러 객체에서 소유하는 경우에는 unique_ptr 를 사용할 수 없다. 이때 사용할 수 있는 스마트 포인터가 shared_ptr 이다. shared_ptr 는 객체의 소멸시점을 관리하기 위하여 reference count 를 사용한다. 이 reference count 가 0 이 되면 메모리를 해제하게 된다. shared_ptr 는 내부적으로 다음과 같이 구현되어 있다. shared_ptr의 크기는 생 포인터의 두 배이다. 생 포인터의 크기와 reference count 를 가르키는 포인터를 갖고 있어야 하기 때문..
std::unique_ptr 는 독점적 소유권 의미론을 재현하는 클래스이다. 그에 따라 복사를 허용하지 않으며, 오직 이동만 가능하다. std::unique_ptr 는 raw 포인터와 거의 같은 크기를 갖는다. 메모리와 CPU 성능이 넉넉하지 않더라도 사용하기에 충분하다는 뜻이다. std::unique_ptr 객체는 자신이 파괴될 때, 가르키는 자원 또한 함께 파괴된다. std::unique_ptr 가 파괴될 때 수행되는 커스텀 삭제자를 사용할 수 있다. 팩터리 패턴의 함수의 예시를 살펴보자. auto delInvmt = [](Investment* pInvestment) { makeLogEntry(pInvestment); delete pInvestment; }; template std::unique_pt..
C++ 에서 말하는 특수 멤버 함수란 C++ 이 스스로 작성하는 멤버 함수들을 가리킨다. 대표적으로 기본 생성자, 소멸자, 복사 생성자 등이 있다. 이 함수들이 생성되기 위한 가장 기본적인 조건은 클라이언트 코드에서 이 함수들을 사용할 때 생성된다. C++11 에 오면서 두 가지의 특수 멤버 함수가 추가됐다. 이 특수 멤버 함수의 조건을 알아보자. 이동 생성자와 이동 배정 연산자 C++ 의 가장 큰 특징이 바로 move semantics 이다. 이와 관련하여 이동 생성자와 이동 배정 연산자가 추가되었다. 이 둘은 아래와 같이 정의된다. class Widget { public: ... Widget(Widget&& rhs); Widget& operator=(Widget&& rhs); ... }; 두 특수 멤..
멤버 함수가 멤버 변수들을 수정하지 않는다면 const 로 선언하는 것이 자연스럽다. 그런데 스레드를 사용한다면 문제가 생길 수 있다. 예시를 통해 살펴보자. mutex의 사용 다음은 다항식의 근을 구는 함수 roots 를 구현하는 상황이다. 성능 향상을 위해 캐싱을 이용하였으며, rootsAreValid 의 값을 이용하여 캐싱 여부를 판별하는 함수이다. class Polynomial { public: using RootsType = std::vector; RootsType roots() const { if(!rootsAreValid) { ... rootsAreValid = true; } } private: mutable bool rootsAreValid{ false }; mutable RootsType..
constexpr 은 객체에 적용했을때는 const 가 되며, 이 값은 컴파일 시점에 알려진다. 컴파일 시점에 알려지는 값들은 읽기 전용 메모리에 배치될 수 있다. 또 다른 장점으로는 컴파일 시점에 정수 상수 표현식이 요구되는 문맥에서 사용할 수 있다는 것이다. 어떤 경우에 사용할 수 있는지 예제를 통해 알아보자. int sz; // 비 constexpr 변수 ... constexpr auto arraySize1 = sz; // error std::array data1; // error constexpr auto arraySize2 = 10; // 10은 상수 std::array data2; // arraySize2는 constexpr 객체 여기서 알아야할것은 constexpr 이 아닌 const 로 선..
서론 noexcept 를 이해하기 전에 C 와 C++ 의 특징에 대해서 알고가는 것이 좋을것 같아 작성한다. C 는 하드웨어를 작성하기 위해 만들어진 언어이다. 그러다보니 프로그래머에게 많은 자유를 주어진다. 예를 들어 다른 언어와 다르게 메모리를 직접 관리할 수 있으며, 하드웨어 제어 또한 가능하다. 대신에 그로 인해 발생하는 댕글링 포인터와 같은 문제에 대해서는 책임지지 않는다. 이러한 특성이 C++ 에도 전달되어서인지 예외에 대한 책임은 온전히 프로그래머의 몫이다. 그로인한 특성으로 try catch 문이 문법으로 존재함에도 STL에서 try catch 문을 사용하지 않는다. 또한 예외에 대해 변경이 생긴다면 기존에 존재하던 프로그램에 문제를 일으킬 수 있다는 이유로 try catch 문과 같은 예..
const_iterator 는 iterator 와 달리 수정하면 안 되는 값들을 가리킨다. 표준 관행에 따르면 가능한 한 항상 const 를 사용하라는 말에 따라 가능하다면 const_iterator 를 사용하는 것이 좋다. 예시를 보면서 이해해보도록 하자. std::vector values; ... std::vector::iterator it = std::find(values.begin(), values.end(), 1983); values.insert(it, 1998); 위의 코드는 1983 이라는 값을 찾아 그 위치에 1998 이라는 값을 삽입하는 코드이다. 여기서 주목해야할 점은 find 함수로 찾은 iterator 를 직접 수정하는 일은 없다는 것이다. 이것을 표준 관행에 따르도록 하면 iter..
C++11에 오면서 override라는 키워드가 생겼다. java를 해본 사람이라면 @override라는 어노테이션을 본 사람이 있을 것이다. 이 어노테이션은 컴파일러에게 오버라이된 함수라는 것을 알려줘서 부모 클래스으로 부터 상속 받을 함수가 없다면 컴파일시에 알려준다. C++에서도 override 키워드가 똑같은 역할을 한다. 오버라이드 키워드를 만족하는 조건은 다음과 같다. 기반 클래스 함수가 반드시 가상 함수이어야 한다. 기반 함수와 파생 함수의 이름이 반드시 동일해야 한다(단, 소멸자는 예외). 기반 함수와 파생 함수의 매개변수 형식들이 반드시 동일해야 한다. 기반 함수와 파생 함수의 const성이 반드시 동일해야 한다. 기반 함수와 파생 함수의 반환 형식과 예외 명세가 반드시 호환되어야 한다...
- Total
- Today
- Yesterday
- C
- C++
- auto
- std::forward
- CPP
- Unreal
- 발아시기
- Future
- 포인터
- std::move
- 보편 참조
- Override
- Effective
- C++14
- forward
- detach
- async
- Join
- C++11
- 람다
- MOVE
- Modern
- thread
- const
- Forwarding
- Perfect
- Overloading
- 다이소
- Effective Modern C++
- 보편참조
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |