박오이님
무미건조한 개발자
박오이님
전체 방문자
오늘
어제
  • 뭥미 (101)
    • 프로젝트 (8)
      • 자가 보호 (3)
      • 주식 시장 분석 도구 (5)
    • 보안 (7)
      • 개론 (2)
      • 웹 (2)
      • 시스템 (2)
    • 개발 (69)
      • C++ (12)
      • Win32 (7)
      • MFC (2)
      • 자료구조 (8)
      • 알고리즘 (22)
      • 백준 (9)
      • 프로그래머스 (4)
      • LeetCode (0)
      • 개발자 면접 준비 (4)
      • OpenGL (1)
    • 서적 (13)
      • Effective C++ (9)
      • Effective Modern C++ (4)
    • 관심사 (4)
      • 재테크 (4)

블로그 메뉴

  • 홈
  • 방명록

공지사항

인기 글

태그

  • 에라토스테네스의 체 #C #C++ #개발 #알고리즘 #BFS #DFS #백준 #백준알고리즘
  • 윈도우
  • 코딩컨벤션
  • CPP
  • C++
  • vcpkg
  • 안경잡이개발자
  • C
  • 나동빈 #알고리즘 #동빈나
  • 윈도우개발자
  • 알고리즘
  • EffectiveC++
  • 시스템프로그래밍
  • 윈도우시스템프로그래밍
  • 백준 #알고리즘 #플로이드와샬 #DFS #BFS #C #C++
  • 플로이드와샬알고리즘 #최단경로 #백준 #알고리즘 #개발 #C #C++
  • Functional
  • 동빈나
  • DFS #BFS #알고리즘 #프로그래밍 #코딩테스트 #코딩 #C++ #C
  • 합집합찾기
  • JSON
  • 크루스칼알고리즘
  • std
  • 최소간선비용
  • jsoncpp
  • 윈도우프로그래밍
  • 나동빈
  • 개발
  • 프로세스메모리
  • 에라토스테네스의 체 #알고리즘 #개발 #C #C++ #소수 #소수판별

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
박오이님

무미건조한 개발자

서적/Effective Modern C++

항목 7: 객체 생성 시 괄호(())와 중괄호({})를 구분하라

2022. 7. 13. 00:59

C++11에서는 객체 생성 구문이 아주 다양해졌다.

C++ 에서는 Class 개념이 있기 때문에 초기화와 배정이 각자 다른 함수들을 호출한다.
정확하게 괄호/중괄호를 이해하고 써야하는 이유이다.

중괄화 초기화를 선호한다.
절대 여기만 보고 페이지 넘기지마세요~
초반에만 중괄호 초기화에 대한 내용을 기술하고, 후반부터는 단점을 기술한다.

장점 1: narrowing conversion을 방지

double x, y, z;
int sum1{ x + y + z};	//	오류! double들의 합을 int로 표현하지 못할 수 있음

괄호나 "="를 이용한 초기화는 이러한 좁히기 변환을 점검하지 않는다.

장점 2: 가장 성가신 구문 해석에 자유롭다는 점
가장 성가신 구문 해석은 "선언으로 해석할 수 있는 것은 항상 선언으로 해석해야 한다"는 C++의 규칙에서 비롯된 하나의 부작용 --> 사실 무슨말인지 이해가 잘 안되는 문장이었다.

Widget w1(10);	//	인수 10으로 Widget의 생성자를 호출
Widget w2();	//	가장 성가신 구문 해석! Widget을 돌려주는, w2라는 이름의 함수를 선언한다.
Widget w3{};	//	인수 없이 Widget의 생성자를 호출

단점 1: 종종 예상치 못한 행동을 보인다.

중괄호 초기치와 std::initializer_list, 그리고 생성자 중복적재 해소 사이에서 발생한다.
이유는 중괄호 초기화 구문은 이상하게도 std::initializer_list를 받는 중복적재 버전을 강하게 선호한다.

class Widget{
public:
	Widget(int i, bool b);
    Widget(in i, double d);
    Widget(std::initializer_list<long double> il);
};

Widget w1(10, true);	//	첫 생성자를 호출
Widget w2{10, true};	//	중괄호를 사용한 경우, std::initializer_list 생성자 호출

Widget w3(10, 5.0);		//	둘째 생성자 호출
Widget w4{10, 5.0};		//	std::initializer_list 생성자 호출

std::initializer_list 생성자가 가능한 최선의 부합인 경우에도 그 생성자를 호출할 수 없는 기현상이 생기기도합니다.

class Widget{
public:
	Widget(int i, bool b);
    Widget(int i, double d);
    
    Widget(std::initializer_list<bool> il);
};

Widget w{10, 5.0}	//	오류!

위 코드를 보면 두 변환 모두 좁히기 변환인데, 중괄호초기화는 좁히기 변환을 허용하지 않으니 오류 발생한다.

변환하는 방법이 없으므로 다시 중복적재 해소의 후보가됩니다.

class Widget{
public:
	Widget(int i, bool b);
    Widget(int i, double d);
    
    Widget(std::initializer_list<std::string> il);
};

Widget w1(10, true);	//	첫 생성자를 호출
Widget w2{10, true};	//	첫 생성자를 호출

Widget w3(10, 5.0);		//	둘째 생성자 호출
Widget w4{10, 5.0};		//	둘째 생성자 호출

std::vecotr만 봐도 괄호와 중괄호는 다르다.

std::vector<int> v1(10, 20);	//	비 std::initializer_list 생성자를 사용 모든 요소의ㅏ 값이 20인, 요소 10 자리 std::vector 생성
                                
std::vector<int> v2{10, 20};	//	값이 각각 10과 20인 두 요소를 담은 std::vector 생성

그래서 뭘 쓰라는거야?가 중요한게 아니다
정리하자면, 

첫째, 클래스를 작성할 때, 만일 일단의 중복적재된 생성자 중에 std::initializer_list를 받는 함수가 하나 이상 존재한다면, 중괄호 초기화 구문을 이용하는 코드에는 std::initializer_list 중복적재들만 적용될 수 있음을 주의해야한다.

둘째, 객체를 생성할 때 괄호와 중괄호를 세심하게 선택

템플릿 안에서 객체를 생성할 때 괄호를 사용할 것인지 중괄호를 사용할 것인지 선택하기가 어려울 수 있다.

저작자표시 (새창열림)

'서적 > Effective Modern C++' 카테고리의 다른 글

항목 8: 0과 NULL보다 nullptr를 선호하라  (0) 2022.08.18
항목 6: auto가 원치 않은 형식으로 연역될 때에는 명시적 형식의 초기치를 사용하라  (0) 2022.07.06
항목 5: 명시적 형식 선언보다는 auto를 선호하라  (0) 2022.07.04
    '서적/Effective Modern C++' 카테고리의 다른 글
    • 항목 8: 0과 NULL보다 nullptr를 선호하라
    • 항목 6: auto가 원치 않은 형식으로 연역될 때에는 명시적 형식의 초기치를 사용하라
    • 항목 5: 명시적 형식 선언보다는 auto를 선호하라
    박오이님
    박오이님
    긍정도 아니고 부정도 아닌 0

    티스토리툴바