6월 30, 2016

[EC++ 02] Prefer consts, enums, and inlines to #defines.

#define 으로 정의한 상수는 preprocessor에 의해 처리가 되어 컴파일러에 잡히지 않는다. 따라서 이 부분에서 실수가 일어나도 컴파일러가 이를 알려줄 수 없기 때문에, 가급적이면 #define의 다른 대체제를 사용하는 것이 좋다.

const

#define을 constants로 바꿔줄 때, 두가지 경우를 고려할 수 있다.

  • Defining constant pointer
  • const 위치에 따른 의미 변화에 유의. [EC++ 03]에서 자세히 다룸.

  • Class-specfic constants
  • static const int value = 5;


enum

"enum hack"

inline

#define function을 정의할 때는 문의 괄호에 반드시 신경써야 함.


Summary

  • For simple constants, prefer const objects or enums to #defines.
  • For function-like macros, prefer inline functions to #defines.

Reference

  • Effective C++ by Scott Meyers

6월 29, 2016

external linkage VS internal linkage

title: external linkage VS internal linkage
tag:

컴파일러는 컴파일 시 translation unit을 생성함.

translation unit
implementation file(*.cpp, *.cxx)에서 생성된 object 파일과 이 파일에서 include 된 모든 헤더 파일을 합친 것.
Internal linkage란 이 translation unit 안의 범위에 있는 것을 의미. 반대로 External linkage란 특정 translation unit의 외부에서도 존재하는 것(즉, 프로그램 어디서든(선언된 파일이 아닌 다른 파일에서도) 접근이 가능한 변수)을 의미.

예를 들어, static은 internal linkage를 가지며 선언된 파일 안에서만 접근이 가능함. 반면에 global variable은 external linkage를 가지며 선언된 파일 바깥에서도 extern 선언만 하면 프로그램 어디서든 접근이 가능함.


Reference

6월 24, 2016

reference type의 null 할당을 위한 static member null object(NullObject) 정의


Synopsis

C++에서 pointer 사용을 줄이기 위해서 가급적 reference type을 사용하려 하는데, pointer가 null 값을 가질 수 있는데 반해 reference type은 null을 가질 수 없어 reference type을 멤버로 갖는 객체 초기화 등에 불편. 이를 해결하기 위해 클래스에 static member로 해당 클래스 타입의 NullObject를 정의하고, 해당 클래스의 reference type이 null 값을 가져야 할 때 이 static null object를 줌.

Example



  1. case 1: NullObject가 정상적으로 작동함.
  2. case 2: NullObject의 주소를 확인 -> 주소 비교를 통해 현재 object가 NullObject인지 아닌지 체크 가능.
  3. case 3: NullObject inheritancy test 1
  4. case 4: NullObject inheritancy test 2

실제 이런 implementation을 사용 시에는 객체가 관련된 프로세스 과정에서 현재 객체가 NullObject인지 아닌지 객체 처리 전에 체크할 수 있는 nullCheck()나 isValid() 등의 멤버 함수를 추가로 정의.



더 생각해볼 점

  • NullObject는 const 선언이 되어야할까?
  • NullObject는 변경이 되선 안되므로 const 선언이 되는게 맞지만, 이 경우 이 NullObject를 받는 다른 reference type들도 모두 const 선언이 되어야하는 문제가 있음. 원래 NullObject는 reference type을 단순히 '임시로 초기화' 하기 위한 임시값인데, NullObject 때문에 reference type이 const reference type으로 선언이 되면 이후 이 reference type을 통해 가르킬 다른 객체들의 내부 값 수정이 불가능해짐.

  • NullObject가 move 또는 copy 된다면?
  • 이 경우도 문제가 생길 것 같은데.. move constructor나 copy constructor에 NullObject의 move나 copy를 막기 위한 NullObject 검사 과정이 필요함.

  • NullObject에 singleton 패턴을 응용할 수 있지 않을까?

Reference

  • -

6월 23, 2016

seekg() VS seekp(), tellg() VS tellp()


  • tellg()
  • get pointer의 현재 위치를 반환함. tellg() 는 input streams 와 함께 쓰이며, stream의 현재 포인터의 'get' position 을 반환함(get pointer의 현재 위치). get pointer는 input sequence에서 다음 input operation이 일어날 위치를 가르킴.

    • pos_type tellg()

  • tellp()
  • put pointer의 현재 위치를 반환함. tellp()는 output streams와 함께 쓰이며, stream의 현재 포인터의 'put' position을 반환함(put pointer의 absolute position을 반환). put pointer는 output sequence에서 다음 output operation이 일어날 위치를 가르킴.

    • pos_type tellp()

  • seekg
  • get pointer의 위치를 변경함. get pointer는 input stream과 관련된 pointer로, input stream과 연결된 source에서 읽어올 다음 위치를 가르킴.

    • istream& seekg(pos) pos로 pointer를 옮김.
    • pos는 absolute value(the value counting from begin of the file).

    • istream& seekg(offset, direction)
    • offset은 stream의 direction으로부터 offset을 direction은 offset을 counting할 기준점. (ios_base::beg, ios_bas::cur, ios_base::end 등이 존재.)

  • seekp
  • put pointer의 위치를 변경함. put pointer는 output stream과 관련된 pointer로, stream object의 output(put or write) file pointer의 위치를 가르킴. 대부분의 경우 stream object의 input file pointer의 위치도 함께 변경시킴.

    • ostream& seekp(pos) pos로 pointer를 옮김.
    • ostream& seekp(offset, direction)

example


output



Reference

6월 21, 2016

[EC++ 01] View C++ as federation of languages.


C++은 처음 도입된 이후 다양한 개념들을 흡수하며 발전한 결과 처음과는 다른 새로운 언어로 재탄생. 그러나 서로 다른 개념들을 통합하는 과정에서 수많은 예외 상황이 발생했고, 그 결과 C++ 에서 모든 상황에 적용되는 통일된 규칙을 찾는 것이 점점 어려워지고 있음. 이런 문제를 해결하기 위해 C++의 언어적 특성을 살펴볼 필요가 있음. C++은 크게 다음 4가지의 주된 언어적 특성을 가지고 있음.

  • C
  • Blocks, statements, preprocessor, built-in data types, arrays, pointers 등. 그러나 대부분의 경우 C++에서는 각 경우에 대응되는 더 나은 방법을 제공하고 있음.

  • Object-Oriented C++
  • encapsulation, inheritance, polymorphism 등

  • Template C++
  • C++의 generic programming 부분에 해당. Template은 TMP(Template Metaprogramming)이라는 새로운 패러다임을 만든 강력한 도구지만, 이를 잘 사용하지 않는다해도 C++에서 큰 문제는 없음.

  • The STL
  • STL(Standard Template Library)는 특별한 template library로, 이를 사용할 때는 STL의 특정한 conventions을 따라야 함.

이 각각의 언어적 특성들은 때때로 서로 갈등을 빗고, 그 결과 다양한 예외 규칙을 만들어 C++에 혼란을 초래함. 따라서 효율적인 프로그래밍을 위해서는, 이러한 sublanguage의 특성을 기억해두고 특정 상황에 따라 그에 맞는 sublanguage를 선택하여 유연하게 전략을 바꿀 수 있어야 함.


Summary

  • Rules for effective C++ programming vary, depending on the part of C++ you are using.

reference

6월 15, 2016

cin으로 대량의 데이터 읽을 때 주의 사항

cin으로 large data를 읽어야 하는 경우, cin.sync_with_stdio(false) 옵션으로 cin과 stdio의 sync를 해제.


explanation

cin은 기본 옵션으로 stdio와 syncronized되어 있음. FILE * 기반의 stdio와 iostream은 각각 구분되는 구현과 버퍼를 가지고 있기 때문에, 만약 두개가 같이 쓰인다면 문제가 생길 수 있음. 이런 문제를 해결하기 위해 stdio와 iostream를 syncronize하는데, 일반적으로 cin이 한번에 하나의 char씩만 읽도록 제한하는 방법을 사용.

그러나 이 때문에 input buffering을 할 수가 없어 많은 데이터를 읽을 경우 이 때문에 오버헤드가 굉장히 커지기 때문에, 대량의 데이터 입력이 필요한 경우 stdio와 cin의 sync를 해제해 주는 것이 좋음.


reference

6월 09, 2016

copy elision ,RVO, NRVO

복사 및 이동 생성자를 zero-copy pass-by-value (무복사 값에 의한 전달)로 최적화 하는 것. 특정 상황(아래 서술)에서 객체의 복사 및 이동 생성자를 생략함. 함수의 return 문과 관련되는 경우 이를 RVO(return by value, return의 argument가 생성자인 경우), NRVO(return by value, 함수 내 local variable을 반환하는 경우) 등으로 부르기도 함.


RVO (Return Value Optimization)

어떤 reference에도 bound되지 않은 nameless temporary 가 복사/이동될 때, 복사/이동 생성자가 생략되고 대신 복사/이동하려는 공간에 직접(바로) 할당됨. nameless temporary 가 return 문의 argument인 경우, 이러한 copy elision을 RVO라 부른다.


NRVO (Named Return Value Optimization)

vs2005부터는 이름있는 변수에도 RVO가 적용되기 시작함.

함수가 class type을 값으로 반환하고, 반환문의 expression이 함수의 파라미터나 catch-cluase의 파라미터가 아닐 때, 복사/이동 생성자가 생략되고 대신 복사/이동하려는 공간에 직접(바로) 할당됨. nameless temporary 가 return 문의 argument인 경우, 이러한 copy elision을 NRVO라 부른다.

단, NRVO는 non-debug mode(release mode), 최적화 옵션 /O1에서부터 적용됨.


사용 방법

return에 move(..)를 사용하지 않는다. 기본 implementaion은 다음과 같음.

  • X에 copy 또는 move constructor가 있으면, 컴파일러가 copy elision을 수행할 수 있음.
  • 이외의 경우, X에 move constructor가 있으면, move constructor가 실행됨.
  • 이외의 경우, X에 copy constructor가 있으면, copy constructor가 실행됨.
  • 이외의 경우, 컴파일 타임 에러가 생략됨.


주의

만약 if 문과 같이 multiple return paths를 갖는 경우 (N)RVO가 수행되지 않음. 그 밖에 컴파일러에 따라 디버그 모드 등 특정한 상황에서 copy elision을 수행하지 않으므로 주의해야 함.


example


  

왼쪽: result in debug mode, 오른쪽: result in non-debug mode(release mode) with /O1 option


reference

6월 08, 2016

cv-qualified type 이란?

type specifier에서 constness나 volatility를 나타내는데 사용되는 표현. const , volatile , mutable 등이 있음.


cv-unqualified type

cv-qualified 가 아닌 모든 type.


reference