종제로
종제로 Devlog
종제로
전체 방문자
오늘
어제
  • 분류 전체보기 (43)
    • C, C++ (22)
      • C, C++ (10)
      • Modern C++ (4)
      • 전문가를 위한 C++ (책) (8)
    • DirectX 자체엔진 개발 (8)
    • 자료구조 알고리즘 (10)
      • 공부 (9)
      • 문제풀이 (1)
    • 자기 계발 (1)
    • 기타 (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 모두의C언어
  • C++
  • 알고리즘
  • DirectX11
  • c++ 11
  • 자료구조
  • C
  • c++ 17
  • 전문가를 위한 C++
  • directX

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
종제로

종제로 Devlog

C, C++/전문가를 위한 C++ (책)

전문가를 위한 C++ : 1장 (2)

2022. 6. 4. 18:02

1. enum과 enum class

enum은 원래 타입을 엄격하게 따지지 않는다.

타입을 엄격히 따지는 것을 '스트롱 타입' 또는 '타입에 안전하다(타입 세이프하다)'고 표현한다.

enum 타입은 항상 정수로 해석하기 때문에 선언한 형태에 관계없이 모든 enum 타입을 서로 비교할 수 있다.

타입을 엄격하게 적용하고 싶다면 enum class를 사용한다.

enum class PieceType
{
	King = 1,
	Queen,		// 2
	Rook = 10,
	Pawn		// 11
};

 

enum class로 정의한 열거 타입 값들의 이름은 스코프(유효 범위)가 자동으로 확장되지 않는다.

다시 말해 enum class 스코프 안에서만 유효하다.

따라서 열거 타입 값을 사용할 때마다 다음과 같이 스코프 지정 연산자를 붙여야 한다.

PieceType piece = PieceType::King;

 

또한 enum class로 정의한 열거 타입 값은 자동으로 정수 타입으로 변환되지 않는다.

그래서 다음과 같이 표현할 수 없다.

void f()
{
	if (PieceType::Queen == 2) { }

	// 명시적으로 형변환하면 가능
	if (static_cast<int>(PieceType::Queen) == 2) { }
}

 

결론 : 열거 타입을 사용할 때는 타입에 안전하지 않은, 즉 타입 언세이프한 enum보다는 스트롱 타입 버전인 enum class로 작성하는 것이 좋다.

 

 

2. c++ 17 if문의 이니셜라이저

c++ 17부터 if문 안에 이니셜라이저(초기자)를 넣는 기능이 추가됐다.

문법은 다음과 같다.

if (<이니셜라이저> ; <조건문>) { <본문> }

 

<이니셜라이저>에서 정의한 변수는 <조건문>과 <본문> 안에서만 사용할 수 있고 if문 밖에서는 사용할 수 없다.

if (Employee employee = GetEmployee() ; employee.salary > 1000) { }

↑ <이니셜라이저>로 직원 정보를 가져와서 조건문에서 그 직원의 급여가 1000 이상인지 확인하고, 이를 만족하면 본문에 나온 코드를 실행한다.

 

 

3. switch

c++에서 switch 문에 지정할 수 있는 표현식은 결괏값이 반드시 정수 타입이거나, 정수 타입으로 변환할 수 있는 타입이거나, 열거 타입이거나, 엄격한 열거 타입이어야 하며, 상수와 비교할 수 있어야 한다.

 

switch 문의 조건으로 지정한 값과 일치하는 case 문이 있다면 그 아래 나오는 문장을 break 문이 나타날 때까지 실행한다.

이때 break 문이 없다면 다음에 나오는 case 문도 계속해서 실행하는데, 이렇게 실행되는 것을 폴스루(흘려보내기)라 부른다.

다음 코드는 여러 case 문에 대해 동일한 코드 블록을 실행하도록 폴스루 방식으로 작성한 예를 보여주고 있다.

switch (backgroundColor)
{
	case Color::DarkBlue:
    case Color::Black:
    // 배경색이 진청 혹은 검정일 때 실행될 코드
    break;
    case Color::Red:
    // 배경색이 빨강일 때 실행될 코드
    break;
}

 

c++17 [[fallthrough]]

폴스루 방식으로 작성하면 버그가 발생하기 쉽다. 예를 들어 중간에 break 문을 깜빡 잊고 빠뜨렸을 경우가 그렇다.

컴파일러가 switch 문에서 폴스루 구문을 발견했는데 위 예제처럼 해당 케이스가 비어 있지 않으면 경고 메시지를 발생한다.

c++ 17부터 [[fallthrough]] 속성을 지정해서 의도적으로 폴스루 방식으로 작성했다고 컴파일러에 알려줄 수 있다.

 

다음은 경고 발생

switch (backGroundColor)
{
    case Color::DarkBlue:
    doSomethingForDarkBlue();
    [[fallthrough]];
}

 

다음은 경고 발생하지 않음

switch (backGroundColor)
{
	case Color::DarkBlue:
    doSomethingForDarkBlue();
    [[fallthrough]];
	case Color::Black:
    // ...
    break;
}

 

추가로, c++ 17부터 if 문처럼 switch 문도 이니셜라이저를 지정할 수 있다. 문법은 다음과 같다.

switch (<이니셜라이저> ; <표현식>) { <본문> }

 

 

4. 논리 연산자

c++은 논리 표현식을 단락 논리(축약 논리) 방식으로 평가한다.

다시 말해 표현식을 평가하는 도중에 최종 결과가 확정되면 나머지 부분은 평가하지 않는다.

예를 들어 다음 코드처럼 여러 개의 부울 표현식에 대한 논리 OR 연산을 평가할 때 결과가 true인 표현식을 발견하는 즉시 나머지 부분은 검사하지 않고 끝낸다.

 

bool result = bool1 || bool2 || (i > 7) || (27 / 13 % i + 1) < 2;
// 여기서 bool1이 true라는 결과가 나오면 
// 표현식 전체가 true일 수밖에 없으므로 나머지 부분은 평가하지 않는다.

 

결론 : 단락 기능은 프로그램 성능을 높이는 데 도움 된다. 단락 되는 논리식을 작성할 때는 가볍게 검사할 수 있는 부분은 앞에 두고, 시간이 좀 걸리는 부분은 뒤에 둔다.

 

 

5. 함수

함수 리턴 타입 추론

c++ 14부터는 함수의 리턴 타입을 컴파일러가 알아서 지정할 수 있다.

이 기능을 적용하려면 다음과 같이 리턴 타입 자리에 auto 키워드를 적는다.

auto addNumbers(int num1, int num2)
{
	return num1 + num2;
}

그러면 컴파일러는 return 문에 나온 표현식의 타입에 따라 리턴 타입을 추론한다.

함수 안에는 return 문이 여러 개가 있을 수 있는데, 이때 각 타입은 모두 같아야 한다.

리턴값으로 재귀 호출문을 지정할 수도 있는데, 이때 재귀 호출이 아닌 return 문도 반드시 함께 지정한다.

 

현재 함수 이름

함수마다 내부적으로 __func__라는 로컬 변수가 정의되어 있다.

이 변수는 현재 함수의 이름을 값으로 갖고 있으며, 주로 로그를 남기는 데 활용한다.

int addNumbers(int num1, int num2)
{
	std::cout << "Entering function " << __func__ << std::endl;
	return num1 + num2;
}

 

 

6. C 스타일 배열

스택 기반의 C 스타일 배열의 크기는 c++ 17부터 제공하는 std::size() 함수로 알아낼 수 있다.

(이 함수를 사용하려면 <array> 헤더를 인클루드해야 한다)

예를 들면 다음과 같다.

int myArray[3] = { 0, };
unsigned int arraySize = std::size(myArray);

 

현재 사용하는 컴파일러가 c++ 17을 지원하지 않는다면 예전 방식처럼 sizeof 연산자로 크기를 구하면 된다.

sizeof 연산자는 인수로 지정한 대상의 크기를 바이트 단위로 리턴한다.

스택 기반 배열에 담긴 원소 수를 알아내려면 이 연산자가 리턴한 값을 첫 번째 원소의 크기로 나눠야 한다.

예를 들면 다음과 같다.

unsigned int arraySize = sizeof(myArray) / sizeof(myArray[0]);

 

 

7. std::array

c++에서는 std::array라는 고정 크기 컨테이너를 제공한다.

이 타입은 <array> 헤더 파일에 정의되어 있다.

사실 C 스타일 배열 위에 한 꺼풀 덮어쓴 것에 불과하다.

 

std::array는 C 스타일 배열에 비해 여러가지 장점이 있다.

  1. 항상 크기를 정확히 알 수 있음
  2. 자동으로 포인터를 캐스팅(동적 형변환)하지 않아서 특정한 종류의 버그를 방지할 수 있음
  3. 반복자(이터레이터)로 배열의 원소에 대한 반복문을 쉽게 작성 가능
std::array<int, 3> arr = { 9, 8, 7 };
unsigned int arrSize = arr.size();

 

 

8. 구조적 바인딩

c++17부터 구조적 바인딩이란 개념이 도입됐다.

구조적 바인딩을 이용하면 여러 개의 변수를 선언할 때 배열, 구조체, 페어 또는 튜플의 값으로 초기화할 수 있다.

예를 들어 다음과 같이 배열이 정의되어 있다고 하자.

std::array<int, 3> values = { 11,22,33 };

이 상태에서 x, y, z란 변수를 선언할 때 각각 앞에 나온 values 배열에 담긴 값으로 초기화할 수 있다.

구조적 바인딩을 적용하려면 반드시 auto 키워드를 붙여야 한다.

예를 들어 auto 자리에 int를 지정하면 안 된다.

auto [x, y, z] = values;

 

구조적 바인딩에서는 왼쪽에 나온 선언할 변수 개수와 오른쪽에 나온 표현식 값 개수가 반드시 일치해야 한다.

구조적 바인딩은 배열뿐만 아니라 모든 멤버가 non-static이면서 public으로 선언된 데이터 구조라면 어떤 것(struct, pair, tuple 등)도 적용할 수 있다.

예를 들면 다음과 같다.

struct Point { double mX, mY, mZ; };
Point point;
point.mX = 1.0; point.mY = 2.0; point.mZ = 3.0;
auto [x, y, z] = point;

 

 

9. 이니셜라이저 리스트

이니셜라이저 리스트는 <initializer_list> 헤더 파일에 정의되어 있으며, 이를 활용하면 여러 인수를 받는 함수를 쉽게 작성할 수 있다.

엄밀히 말해 initializer_list는 클래스 템플릿이다.

그래서 vector에 저장할 객체의 타입을 지정할 때처럼 원소 타입에 대한 리스트를 꺾쇠괄호로 묶어서 지정해야 한다.

예를 들면 다음과 같다.

#include <initializer_list>
using namespace std;

int makeSum(initializer_list<int> lst)
{
	int total = 0;
	for (int value : lst)
	{
		total += value;
	}
	return total;
}

int main()
{
	int a = makeSum({ 1, 2, 3 });
	int b = makeSum({ 10, 20, 30, 40, 50, 60 });
}

 

이니셜라이저 리스트는 타입에 안전(타입 세이프)하다.

그래서 이니셜라이저 리스트를 정의할 때는 지정한 타입만 허용한다.

앞에서 makeSum() 함수를 정의할 때 이니셜라이저 리스트에 정수 타입 원소만 들어가도록 지정했다.

그래서 다음과 같이 인수로 double 타입 값을 지정하면 컴파일 에러 또는 경고 메시지가 출력된다.

int c = makeSum({ 1, 2, 3.0 });		// 오류 발생

 

 

참고

  • 전문가를 위한 c++ 책
저작자표시 비영리 변경금지

'C, C++ > 전문가를 위한 C++ (책)' 카테고리의 다른 글

전문가를 위한 C++ : 2장 스트링 (2)  (0) 2022.06.09
전문가를 위한 C++ : 2장 스트링 (1)  (0) 2022.06.08
전문가를 위한 C++ : 1장 (4)  (0) 2022.06.07
전문가를 위한 C++ : 1장 (3)  (0) 2022.06.06
전문가를 위한 C++ : 1장 (1)  (0) 2022.06.03
    'C, C++/전문가를 위한 C++ (책)' 카테고리의 다른 글
    • 전문가를 위한 C++ : 2장 스트링 (1)
    • 전문가를 위한 C++ : 1장 (4)
    • 전문가를 위한 C++ : 1장 (3)
    • 전문가를 위한 C++ : 1장 (1)
    종제로
    종제로

    티스토리툴바