[delete]

 

특정 함수의 사용을 명시적으로 막는다.

 

class Knight
{
private:
	void operator=(const Knight& k);
};

과거 사용하던 방식은 멤버 함수를 private으로 설정하고 정의를 안하는 방식이었는데, 이런 경우 빌드에서는 문제가 없으나 정의가 안되어 있으므로 해당 함수에 접근시 링크 단계에서 에러가 발생하게 된다.

그렇기 때문에 에러가 조기에 발견되지 않는 문제가 발생한다.

 

class Knight
{
public: // public으로 두는게 통상적인 관례
	void operator=(const Knight& k) = delete;
};

 이렇게 delete를 붙여주게되면 해당 함수에 접근하는 경우 빌드시 에러를 잡아줄 수 있다.

 

[override, final]

 

가상함수와 연관성이 있다.

 

class Creature
{
};

class Player : public Creature
{
public:
	virtual void Attack() {}
};

class Knight : public Player
{
public:
	virtual void Attack() {}
};

int main()
{
	Creature* player = new Knight();
	player->Attack(); // 사용 불가!
    
    delete player;
    return 0;
}

가상함수의 문제는 현재 내 클래스에서 최초로 정의한 함수인지, 혹은 부모 클래스에서 정의된 함수인지를 알 수 있는 방법이 없다.

 

class Player : public Creature
{
public:
	virtual void Attack() {}
};

class Knight : public Player
{
public:
	virtual void Attack() override {} // 오버라이딩을 명시
};

오버라이딩한 멤버 함수에 override 키워드를 붙여줌으로써 상속받은 가상 함수라는것을 명시적으로 표현할 수 있다.

실수 방지 및 가독성이 좋아지게 된다.

C#에서는 기본적인 문법이다.

 

 

final은 재정의를 막는 키워드이다.

'C++ > Rookiss C++' 카테고리의 다른 글

[Modern C++] 전달 참조(forwarding reference)  (0) 2022.08.31
[Modern C++] 오른값 참조 (rvalue reference)  (0) 2022.08.31
[Modern C++] #1  (0) 2022.08.31
[STL] algorithm  (0) 2022.08.31
[STL] set, multimap, multiset  (0) 2022.08.31

C++11부터를 Modern C++로 분류한다.

 

[auto]

 

auto, template 같은 타입 추론을 형식 연역(type deduction) 이라고 한다.

 

주의사항으로 기본 auto는 const, reference를 무시하므로 명시적으로 붙여주어야만 한다.

int a = 3;
int& ref = a;
auto = ref // int&가 아닌 int형으로 잡힌다

 

일반적인 상황에서는 가독성을 위해 기존 타입을 사용하는게 나을수도 있다.

다만, 타입이 너무 긴 경우 (컨테이너의 pair, iterator 등)

 

[중괄호 초기화]

 

vector 등 컨테이너와 잘 어울린다.

축소 변환을 방지한다.

int x = 0;
double y = x; // y(x) 둘다 허용

double y{x}; // 컴파일 에러!

 

객체를 중괄호 초기화로 생성자를 불러오는 경우, initializer_list 생성자를 만들어주어야 한다.

class Knight
{
public:
	Knight(initializer_list<int> li)
    {
    	// do something
    }
};

 단, 이니셜라이저 리스트 생성자가 존재하면 중괄호 초기화 시 무조건 이니셜라이저 리스트 생성자만 호출이 된다.

 

괄호 초기화

- 전통적인 C++ (거부감이 없음)

- vector 등 특이 케이스에 대해서만 {} 사용

 

중괄호 초기화

- 초기화 문법의 일치화

- 축소 변환 방지

 

[nullptr]

 

오동작을 방지한다.

가독성이 좋아진다.

 

[using]

 

typedef을 대체할 수 있는 문법

typedef int id;
using id2 = int; // typedef과 순서가 반대

 

직관성이 좋아진다.

typedef void (*MyFunc)();
using MyFunc2 = void(*)();

 

typedef은 템플릿을 활용할 수 없지만 using은 가능하다.

 

[enum class]

 

scoped enum

 

이름공간 관리에 이점이 있고 암묵적인 변환이 금지된다.

 

enum Player { NONE, .. };
enum Monster { NONE, .. }; // 재정의 오류

기존 enum은 범위가 전역이기 때문에 중복된 이름을 사용할 수 없다.

 

enum class ObjectType1 { PLAYER, .. };
enum class ObejctType2 { PLAYER, .. };

ObjectType1::PLAYER;
ObjectType2::PLAYER;

enum class는 이름 공간으로 잡히기 때문에 중복된 이름 사용이 가능하다.

 

기존 enum은 암시적인 형변환이 가능했지만 enum class는 오로지 같은 enum class 타입끼리만 연산이 가능해진다.

장점이 될 수도 있고 단점이 될 수도 있다.

 

enum class ObjectType { PLAYER, MONSTER };

int t1 = ObjectType::PLAYER; // 컴파일 에러
int t2 = static_cast<int>(ObjectType::PLAYER); // 형 변환을 해야만 가능

'C++ > Rookiss C++' 카테고리의 다른 글

[Modern C++] 오른값 참조 (rvalue reference)  (0) 2022.08.31
[Modern C++] #2  (0) 2022.08.31
[STL] algorithm  (0) 2022.08.31
[STL] set, multimap, multiset  (0) 2022.08.31
[STL] map  (0) 2022.08.31

자주 사용되는 것들

find, find_if

count, count_if

all_of, any_of, none_of

for_each

remove, remove_if

 

find: 찾으면 찾은 값의 iterator, 못찾으면 end를 반환한다.

 

find_if: 찾으려는 값 대신 함수 객체/함수 포인터를 인자로 넘겨준다. 함수 객체/함수 포인터가 조건이 되며 bool을 반환해 주는 형태여야 한다.

 

count: 찾은 값의 개수를 반환해준다.

 

count_if: 조건에 맞는 값 개수를 반환해준다.

 

셋 다 bool을 반환해준다.

 

all_of: 모든 데이터가 조건에 맞는가?

any_of: 조건에 맞는 데이터가 하나라도 있는가?

none_of: 모든 데이터가 조건에 맞지 않는가?

 

for_each: 범위 내의 모든 데이터에 대해 함수 객체/함수 포인터를 실행한다.

struct MultiplyBy3
{
    void operator()(int& n)
    {
        n = n * 3;
    }
};

for_each(v.begin(), v.end(), MultiplyBy3());

 

remove: 아래와 같다.

 

remove_if: 이름과는 달리 데이터를 실제로 지워주지는 않고 앞으로 땡겨와서 채워준다. 예를들어 값 6개중 3개가 조건에 맞았다면, 조건에 맞는 값 3개를 앞으로 땡겨오고 4번째부터는 방치가 된다.

다만 4번째 위치의 iterator가 반환이 되므로 해당 위치부터 끝까지 erase 해주면 의도하는 결과를 낼 수 있다.

auto it = remove_if(v.begin(), v.end(), IsOdd());
v.erase(it, v.end());

// 아래와 같이 한줄로 쓸수 있음
v.erase(remove_if(v.begin(), v.end(), IsOdd()), v.end());

'C++ > Rookiss C++' 카테고리의 다른 글

[Modern C++] #2  (0) 2022.08.31
[Modern C++] #1  (0) 2022.08.31
[STL] set, multimap, multiset  (0) 2022.08.31
[STL] map  (0) 2022.08.31
[STL] deque  (0) 2022.08.31

set는 key와 value가 일치하는 map이다 라고 이해하면 된다.

set는 가끔 활용한다. (예: 찾은 몬스터 ID의 목록을 가져와야 하는데 그 목록중에 찾고싶은 몬스터가 있는지 빠르게 찾아야 할 때, 이미 찾은 몬스터인지 아닌지를 확인한다던지 하는 경우)

 

multimap과 multiset은 잘 활용하지 않음.

 

multimap은 [] 연산자를 지원하지 않는다.

key값으로 erase를 하는 경우 key의 내용이 다 날아간다.

equal_range: key값에 해당하는 iterator 2개를 pair로 반환해준다. (key의 begin, end)

lower_bound: key값의 begin을 반환해준다.

upper_bound: key값의 end를 반환해준다.

 

map과 set은 면접 질문으로 나오는 경우 보통 어떤 구조로 되어있는지 물어보기도 하지만 가끔 map과 multimap의 차이를 물어보는 경우도 있다.

'C++ > Rookiss C++' 카테고리의 다른 글

[Modern C++] #1  (0) 2022.08.31
[STL] algorithm  (0) 2022.08.31
[STL] map  (0) 2022.08.31
[STL] deque  (0) 2022.08.31
[STL] list  (0) 2022.08.31

vector나 list같은 선형 자료구조의 가장 큰 단점은 데이터를 빠르게 찾을 수 있는 마땅한 방법이 없다.

 

map

균형 이진 트리(AVL)로 만들어졌다.

 

erase는 여러번 호출한다고 딱히 문제가 발생하지는 않는다. 삭제된 키의 개수를 반환해준다.

insert시 이미 key가 존재하는 경우 기존 값이 바뀌지는 않는다. pair<iterator, bool>를 반환해준다.

 

iterator는 pair로 key와 value를 묶어서 레퍼런스로 반환해준다.

 

[] 연산자 사용할 때 주의점은 대입을 하지 않더라도 key-value형태의 데이터가 추가된다.

'C++ > Rookiss C++' 카테고리의 다른 글

[STL] algorithm  (0) 2022.08.31
[STL] set, multimap, multiset  (0) 2022.08.31
[STL] deque  (0) 2022.08.31
[STL] list  (0) 2022.08.31
[STL] vector  (0) 2022.08.30

+ Recent posts