3월 23, 2017

[EC++ 17] Store  new ed objects in smart pointers in standalone statements.


processWidget(std::tr1::shared_ptr(new Widget), priority());

위 코드는 1. new  메모리 할당 ->  shared_ptr  ctor call ->  priority()  call의 세 단계에 걸쳐 수행된다. 그런데 컴파일러에 의해  shared_ptr  ctor call과  priority()  call의 순서가 바뀔 수 있는데, 이 경우  priority() 가 예외를 던지면 memory leak이 발생하게 된다. 따라서  new ed object를   shared_ptr 에 넘겨주는 부분은 별도의 문장으로 따로 빼내는 것이 좋다.



Summary

  • Store  new ed objects in smart pointers in standalone statements. Failure to do this can lead to subtle resource leaks when exceptions are thrown.

Reference

  • Effective C++ by Scott Meyers

3월 22, 2017

[EC++ 16] Use the same form in corresponding uses of   new   and   delete  


  • 일반적으로 single object 와 array는 메모리 상의 구조가 다르다. single object는 메모리 상에 해당 object가 차지하는 공간만이 할당되지만, array는 메모리 상에 array의 크기를 먼저 기록하고 그 다음에 실제 object의 공간을 할당한다.
  • single object와 array는 메모리 상에 할당 되는 구조가 다르기 때문에 new와 delete를 사용하는 방법도 다르다. 따라서 single object와 array는   new    delete  를 사용하는 방법이 서로 다르며, 이를 뒤섞어 쓰면 안된다.
  • 이런 차이점 때문에, 클래스 설계 시 어떤 클래스가 동적 할당한 메모리를 가르키는 포인터를 멤버로 가지면서 여러 버전의 constructor를 제공한다면, 모든 constructor가 해당 포인터를 초기화하는데 모두 같은 형태의   new   를 사용하도록 주의해야 한다.
  •   typedef  를 사용할 때도 주의해야 한다. 예를 들어, array에 typedef를 사용하면 사용자는 typedef 된 자료형이 array인지 모르기 때문에 별 생각없이   new  -  delete  를 사용할 수 있다. 이 경우,   new[]    delete  를 같이 사용하는 것 같다.



Summary

  • If you use [] in a   new  expression, you must use [] in the corresponding   delete  expression, If you don't use [] in a   new  expression, you mustn't use [] in the corresponding   delete  expression.

Reference

  • Effective C++ by Scott Meyers

12월 20, 2016

[EC++ 15] Provide access to raw resources in resource managing classes.


resource leak 방지는 well-designed system의 필수 요소 중 하나이다. 이런 목적으로 resource 관리에 RAII class가 사용되지만, 때로는 resource에 직접 접근할 수 있는 방법이 필요하다. 많은 API가 자신의 parameter로 resource를 받아 이에 직접적으로 접근하기 때문에, 이런 API를 활용하기 위해 RAII class는 자신이 관리하는 resource에 직접 접근할 수 있는 수단을 제공해야 한다. 이러한 접근 수단에는 explicit, implicit 두가지 방식이 있다.

  • explicit
    •  get()  method 제공
  • implicit
    • overloaded derefencing operator( -> ),  * ) 사용
    • overloaded type conversion operator 사용

단, implicit conversion은 편리한 반면 오류의 원인이 되기도 하므로 신중하게 사용해야 한다. 아래의 프로그래밍 의도는 Font 객체의 복사였지만, 실제로는 f1이 FontHandle로 형변환 된 후 이것이 복사된다. font handle은 원래 Font class를 통해 관리되고 접근 가능해야 하지만, 실행 결과 이를 관리하는 RAII 객체를 통하지 않고도 직접적으로 접근이 가능해졌다.



Conclusion

RAII class가 explicit conversion과 implicit conversion 등 어떤 access 방법을 제공할지는 해당 RAII class가 수행하는 작업과 RAII class가 사용되는 상황에 따라 달라진다. 가장 좋은 design 방법은 interface을 올바르게 사용하기 쉽고 잘못 사용하기는 어렵게 만드는 것이다.

RAII class 내부의 raw resource를 반환하는 메소드를 제공하는 것은 C++의 encapsulation 원칙을 어겨 C++의 원칙과 모순되는 것처럼 보인다. 그러나 RAII class의 목적은 raw resource의 관리이지 encapsulation이 아니다. 뿐만 아니라  std::shared_ptr 과 같은 RAII class는 true encapsulation으로 구현되어, underlying resource의 loose encapsulation과 결합하여 결과적으로 더 강한 encapsulation을 제공한다.



Summary

  • APIs often require access to raw resources, so each RAII class should offer a way to get at the resource it anages.
  • Access may be via explicit conversion or implicit conversion. In general, explicit conversion is safer, but implicit conversion is more convenient for clients.

Reference

  • Effective C++ by Scott Meyers

12월 13, 2016

[EC++ 14] Think carefully about copying behavior in resource-managing classes.


Synopsis

mutex를 사용하는 경우,  lock(..)  unlock(..) 을 매 번 잊지 말아야 한다. 이를 해결하기 위해 RAII(Resource Acquisition Is Initialization) class의 사용을 고려해 볼 수 있다.



RAII object의 copy behavior 정의

  • Prohibit copy
  • RAII 객체의 copy operation을 허용하지 않아야 하는 경우가 많이 있다. 예를 들어 underlying resource가  std::mutex 인 경우 copy operation은 의미가 없을 뿐 아니라, 잘못된 동작을 초래할 것이다.

  • Reference-count the underlying resource
  • 동일한 객체가 여러번 사용되는 경우, 마지막 사용이 끝난 시점에서 resource가 release 되어야 한다. 이런 경우 적합한 방식이 reference-counting 방식으로,  std::shared_ptr 와 같은 구현 예가 있다.

    만약 자신의 RAII class에 reference counting 방식을 도입하고 싶다면 referece counting을 직접 구현하지 않고,  std::shared_ptr 을 멤버 필드로 정의하여 같은 효과를 볼 수 있다. Synopsis의 Lock class를 이러한 방식으로 구현할 수 있는데, 이 경우 RAII class의 Reference-count가 0이 되어도 mutex가 destruct되어선 안된다. 이 구현은  std::shared_ptr 의 deleter를 지정하여 해결할 수 있다.

  • Copy the underlying resource
  • Resource-managing class를 사용하는 이유가 오직, heap 메모리의 자동 해제 뿐인 경우, 동일한 resource의 카피를 여러 개 보유할 수도 있다. 이런 경우 resource-managing class의 copy operation은 해당 객체의 underlying resource를 deep-copy 해야 한다.

  • Transfer ownership of the underlying resource
  • copy behavior가 해당 객체의 underlying resource의 ownership을 이양하는 경우를 생각해 볼 수 있다. 이러한 구현의 예로  std::unique_ptr 가 있다.



Summary

  • Copying an RAII object entails copying the resource it manages, so the copying behavior of the resource determines the copying behavior of the RAII object.
  • Common RAII class copying behaviors are disallowing copying and performing reference counting, but other behaviors are possible.

Reference

  • Effective C++ by Scott Meyers

12월 12, 2016

SQL DML(Data Manipulation Language) tag:


SELECT

  • Syntax
  • SELECT [table.]attrib1, [table.]attrib2, ...
    FROM table1, table2, ...
    [WHERE search_condition]
    [GROUP BY attrib1, attrib2, ...]
    [HAVING search_condition]
    [ORDER BY order_expression[ASC|DESC]];
  • 조건 연산자
    • 비교연산자 : =, =>, =<, >, <, IN 등

    • 논리연산자 : AND, OR, NOT 등

    • LIKE연산자 : *(%), ?(_), # 등의 기호를 사용해 문자열을 검색

    • BETWEEN : 특정 값의 사이에 있는 튜플을 검색

  • group funtions :  WHERE  SELECT 와 함께 사용되어 표시할 튜플을 선택하는 기준이 된다면,  HAVING  GROUP BY 와 함께 사용되어 그룹을 묶는 기준이 된다. 하나의 그룹을 모집합으로 사용되는 함수로, 일반적으로  HAVING  절과 함께 사용되어 그룹에 대한 조건을 지정한다.
    •  COUNT(attrib 그룹별 튜플의 수를 구한다
    •  MAX(attrib 그룹별 최대값을 구한다
    •  MIN(attrib 그룹별 최소값을 구한다
    •  SUM(attrib 그룹별 합계를 구한다
    •  AVG(attrib 그룹별 평균을 구한다

INSERT

  • Syntax
  • INSERT INTO table_name(attrib1, attrib2, ...)
    VALUES(value1, value2, ...);
  • 테이블의 모든 속성 값을 입력하는 경우에는 table_name 뒤의 속성명을 생략할 수 있다.
  •  SELECT  문을 사용하여 추출한 검색 결과를 삽입할 수도 있다.

DELETE

  • Syntax
  • DELETE FROM table_name
    WHERE condition;
  •  WHERE  절을 생략하는 경우 해당 테이블의 모든 튜플이 삭제된다.

UPDATE

  • Syntax
  • UPDATE table_name
    SET attrib1=value1, attrib2=value2, ...
    WHERE condition;

reference

12월 07, 2016

\b의 용도


 \b

 \b 는 back space를 의미하는 escape sequence로,  \n 과 같이 다음 출력의 위치를 바꿔주는 역할을 한다.  \n 는 다음 출력의 위치를 다음 줄로 바꿔주는데,  \b 는 다음 출력의 위치를 이전으로 한칸 이동(back space) 한다. 아래 예를 참고하자.

cout << "asdf";    // (1) asdf
cout << "1234";   // (2) asdf1234

(1)이 실행되면 콘솔에서 asdf가 출력된다. 출력을 계속하면 다음에 출력할 문자는 f 뒤부터 출력이 되는데, 이는 콘솔 상에서 마지막 출력의 다음 위치를 cursor가 가르키고 있다가 출력이 재개되면 cursor의 위치부터 출력을 계속하기 때문이다. 만약 되돌려진 커서의 위치에 기존 출력의 내용이 있다면 기존의 출력을 새로운 출력으로 덮어쓰게 된다.

// _ (underline)은 커서의 위치
cout << "asdf";    // (3) asdf_
cout << '\b';        // (4) asdf
cout << "1234";   // (5) asd1234_

이를 응용해 이미 출력된 내용을 지울 수도 있다.

// \b로 커서를 하나 되돌린 후 ' '(공백)을 출력해서 기존 출력을 지운 후, 다시 커서를 되돌림
cout << "asdf";    // (6) asdf_
cout << "\b \b";    // (7) asd_

reference

12월 03, 2016

Regular expression 정규 표현식


Regular expression이란?

정규표현식 혹은 정규식이라고도 부른다. Regular expression(regex or regexp)은 특정한 규칙을 가진 문자열을 표현하는데 사용하는 형식 언어이다. regex는 VIM, EMACS 등 많은 텍스트 편집기와 다양한 프로그래밍 언어에서 문자열의 검색과 치환을 위해 지원하고 있다.

regex 문법은 편집기 별로, 프로그래밍 언어별로 전체적으로는 비슷하지만 조금씩 다른 부분이 있기 때문에, 사용 시에는 이런 부분에 유의하며 사용해야 한다.


요소

  • abc...   letters
  • 123...   digits
  • \d   any digits
  • \D   any non-digit character
  • .   Any character
  • \.   period
  • [abc]   only a, b, or c
  • [^abc]   not a, b, nor c
  • [a-z]   chracters a to z
  • [0-9]   numbers 0 to 9
  • \w   any alphanumeric character
  • \W   any non-alphanumeric character
  • {m}   m repetitions
  • {m, n}   m to n repetitions
  • *   zero or more repetitions
  • +   one or more repetitions
  • ?   optional character
  • \s   any white space
  • \S   any non-white space
  • ^...$   starts and ends
  • (...)   capture group
  • (a(bc))   capture sub-group
  • (.*)   capture all
  • (abc|def)   matches abc or def


reference