본문 바로가기
Programming/Tips(C++,C#)

Chapter 2. C++와 표준 라이브러리 소개

by 곰네Zip 2014. 10. 24.

*이 포스팅은 개인 학습을 위해 내용을 정리한 것이 목적입니다.  

 

2.2 C++언어의 새로운 특징

 2.2.1 Template 

  -하나 이상의 정해지지 않은 임의의 데이터 타입을 위해 작성된 함수 or 클래스.

    -> 타입을 인자로 전달할 수 있음

  -컴파일을 위해 해당 타입에 대해 컴파일 되어 있을 것.

    -> 컴파일 과정 중에 어떤 자료형으로 호출될 지 결정

 * ‘typename’ vs ‘class’

    typename은 파라미터가 어떤 형인지 저 분명하게 만들지만 최근의 컴파일러는 두가지를 동일하게 취

  급class만 적용가능할 땐, class를 사용하고, class가 아닌것도 적용가능할 때엔, typename을 사용.

  (Herb Scutter의 파라미터 즐겨쓰는 구분법 발췌’)

 

* 인라인함수 : 프로그램 코드 가운데 컴파일된 함수코드가 들어감. 함수 진입점을 찾아 점프하여야 할 필

 요가 없으므로 수행속도에 이득. (inline키워드를 사용)

 짧은 함수를 인라인 함수로 사용하자. 

  - 함수 호출비용의 절약

  - 짧은 인라인함수는 함수 호출문에 대해 만들어지는 코드보다 목적 코드가 작아질 수 있음

  - 캐시 적중률이 높아짐

 

* export : 클래스 템플릿을 선언한 파일 외에 다른 파일에서도 사용할 수 있게 하기 위함. 그러나 지원하지

  않는 경우가 많음.translation unit에서 다른 경계에 있는 템플릿을 가져다 써야하는 문제가 있음. (아닐 경

  우 매번 헤더를 추가해주어야 함)

  

- 비타입(non type) 템플릿 파라미터 : 타입의 일부. 예로, bitset은 비트의 개수를 인자로 전송 가능하다.

- 디폴트 템플릿 파라미터 : 여러 인자를 파라미터로 받아오는 함수로, 파라미터가 부족할 경우 미리 정의

  해둔 기본 파라미터를 사용함.

- 멤버템플릿 : 클래스의 멤버 함수는 템플릿이 될 수 있음. 그러나 기본인자 못 가지고 virtual이 안됨.

만약 데이터 타입이 다른데 해당 클래스의 멤버를 호출하면 에러가 남. 함수를 템플릿으로 만들어 처리

2.2.3 예외처리

 c++에서 예외 발생하여 throw를 한 경우
 예

class Error;

if( 예외 조건){

   throw Error(); // class Error를 생성하여 예외로 던짐

}

   위 구문에서 throw구문은 stack unwinding을 수행함.

     * stack unwinding : 호출스택에 서브루틴을 적재하는 스택와인딩의 반대. 서브루틴들을 제거하는 역할.

      모든 로컬 객체들이 예외로 인하여 프로그램을 빠져나갈 때, 소멸자 호출을 보장하여 줌. 이 과정은  

      main()을 빠져나가거나 catch구문을 만날 때 까지 동작함.

    * exception specification : 예외전문화. 해당 함수에서 어느 예외를 던질 지 정의하여 줌. 발생가능한 예

     외를 지정하여 줌.

      - 예외 지정의 목적

        1) 함수를 사용하는 쪽에서 해당 함수에서 어떤 예외가 발생할 수 있는지 알 수 있어 코드만으로 문서

          화의 의미를 가질 수 있다.

        2) 예외지정에 일관성이 없을 경우 컴파일 타임에 알 수 있다.

      - 지정되지 않은 예외가 발생할 경우

         지정된 타입과 다른 타입의 예외가 발생하면 런타임 에러가 발생하면서 unexpected가 호출

         unexpected의 기본 동작은 terminate의 호출. -> 비정상 종료됨

      - 예외 지정 시 주의사항

        1) 예외 지정은 함수 실행 중에 발생할 수 있는 모든 예외에 대한 정보를 제공해야 하므로, 자신이 던

          지는 예외뿐만 아니라 이 함수가 호출하는 함수에서 발생할 수 있는 예외까지 지정해야 함

        2) 컴파일러가 해주는 예외지정 일관성 점검은 극히 부분적

        3) 템플릿에는 예외지정을 하는것 자체가 무의미 (매개변수가 너무 다양하다)

        4) 예외처리코드가 준비되어도 예외 지정 이외의 예외 발생은 처리코드에서 처리 못할 수 있다.

       (참조 : http://dstein.egloos.com/viewer/2518982)

  2.2.4 namespace

    - 식별자들을 이름이 있는 범위를 사용하여 그룹화하는데 사용.

    - using키워드를 사용하여 모든 식별자들을 사용가능하게 해줄 수 있다. 그러나, using이 많아져 같은 이

     름의 다른 식별자가 존재할 경우 오류가 발생된다.

 

  2.2.5 bool타입

   논리적 true/false를 지원하는 타입. 0일 경우 false.

 

  2.2.6 explicit

    단일 인자를 가지는 생성자가 암시적 형변환이 일어나는 것을 막을 수 있음.

       -> 컴파일 타임에 체크하여 준다.

    예) 인자로 stack의 초기 사이즈를 가져오는 생성자 정의시

class Stack{

   explicit Stack(int size);

   ...

}

 

Stack s;

s = 40; //이 구문에서 size가 40인 Stack을 새로 생성하고 이를 s에 할당한다. (explicit이 없을 경우)

          // explicit을 추가하여, 위 구문이 컴파일타임에 에러가 발생하게 한다.

Stack s1(40); // OK

Stack s2 = 40; //error

 

    * 이 키워드는 클래스 내 ctor(생성자)선언에만 적용 가능하다.

      암시적 형변환이 확실히 필요하지 않을 경우 모든 단일인수 생성자를 명시적으로 표기하는게 좋음

    (참조 : http://msdn.microsoft.com/ko-kr/library/h1y7x448.aspx)

 

  2.2.7 casting연산자

1) static_cast : 논리적으로 값을 변환. 변환된 값으로 초기화된 임시 객체를 생성함.

  - 용도 및 제약사항

    i) 실수형과 정수형, 정수형과 열거형 등, 기본 데이터 타입 간의 변환

    ii) 상속관계의 클래스 계층간의 변환

       - 런타임 타입 검사 하지 않음

       - 다형성이 없어도 변환 가능

       - 다중 상속에서 기본 클래스 간의 타입 변환은 못함

    iii) void포인터를 다른 타입의 포인터로 변환

    iv) 서로 다른 타입의 포인터 간의 타입 변환은 못함

   ex)

float x;

...

cout << static_cast<int>(x); << x를 int로 출력

    > 기존 C스타일의 캐스팅과 동일하다.

     -> 원래 표현식이 가지고 있는 상수성을 떼어버리지 못한다.  

    > 정적으로 형변환을 해도 아무런 문제가 없다. -> 정확히 어떤 녀석인지 알고 있을 경우에 해당.

 

2) dynamic_cast : 다형성을 띄고 있는 타입을 실제타입으로 변환(downcast)하는 것을 가능하게 함.

   타임에만 검사됨 

   ex)

class car; //기본클래스

class Cabriolet : public Car{ ... };

class Limousine : public Car{ ... };

 

void f(Car* cp)

{

   Cabriolet* p = dynamic_cast<Cabriolet*>(cp);

   if( p == NULL)

   {

      //p는 Cabriolet타입이 아님

      ...

   }

}

    -> 이 타입을 반드시 질의해 보아야 함

   다운캐스팅에서 사용한다. (업캐스팅시엔 굳이 사용할 필요가 없음). 다형성을 띄지 않은 객체간 변환은 불가능

  * VC6.0에서 RTTI옵션이 꺼져있으면 위 구문에서 Crash!

 

3) const_cast : 어떤 타입에 상수성을 추가/제거하는데 사용됨 

 const int* pConstInt = new int(10);

 int* pInt = const_cast<int*>(pConstInt);

 *pInt = 200;

 cout << *pConstInt << endl;

  > *pInt와 *pConstInt가 가리키는 값은 다르다.

     *pConstInt = 10, *pInt = 200

     const_cast에서 포인터 타입이 아닌 경우 에러 발생한다.

 

4) reinterpret_cast : 포인터가 다른 포인터 형식으로 변환될 수 있게 함. 

 reinterpret_cast<type-id>(expression)

  - 원하는 변환이 본질적으로 저수준이 아닌 한, 다른 캐스트 연산자를 사용해야 함.

  - char* -> int*나, one_class* -> unrelated_class*가 가능. 안전하지 않다.

  - 이 캐스팅 결과는 원래형식으로 캐스팅하는 것 외에 용도로 안전하게 사용할 수 없다.

  - const, volatile또는 __unaligned 특성을 캐스팅 할 수 없다. 이러한 특성을 제거하려면 const_cast로

   -> 변환관계가 명확하거나 특정 목적을 달성할 때만 사용하는게 바람직하다.

 (참조: http://msdn.microsoft.com/ko-kr/library/e0w9f63b.aspx)

 

 

참조 : C++ Standard Library - A tutorial and Reference

반응형

댓글