본문 바로가기

분류 전체보기40

4일차 - 완벽한 전달자 (perfect forwarding) (1) Intro  앞에서 다룬 std::function과 std::bind를 이용한 간단한 예제 하나를 살펴보자.#include #include using namespace std;void foo (int& n) { n = 0; }int main(int argc, char* argv[]){ int x = 10; function f; f = bind(&foo, x); f(); //  맨 마지막 cout의 출력값은 얼마일까? 아마도 의도대로라면 참조인자를 0으로 바꾸는 함수를 호출했으니 0이 출력되어야 맞다. 그런데 코드를 수행해보면 10이 출력된다. 여기서 무슨 일이 일어났는지 파악하기 위해 STL보다 좀 더 간단한 예제로 접근해보자.문제의 단순화 - lockAndCall#include using namesp.. 2015. 7. 23.
4일차 - 범용적 함수 포인터 (general-purpose function pointer) Intro  다음은 단순한 Button 클래스를 구현하고 이를 테스트하는 코드이다.#include using namespace std;void foo () { cout   Button 객체는 인자도 없고, 반환값도 없는 함수 하나를 받아서 핸들러로 지정한다. 그리고 클릭 이벤트가 발생하면 지정된 핸들러를 호출하도록 되어있다. 큰 문제는 없어보이지만 만약에 핸들러를 일반 함수가 아닌 객체의 멤버의 함수를 지정하고 싶은 경우는 어떻게 해야 할까? handler를 멤버함수 포인터 타입으로 선언하면 될 것 같지만, 이렇게하면 반대로 일반 함수를 핸들러로 지정할 수가 없다.std::function  C++ 표준에서는 범용적 함수 포인터 역할을 위해 std::function 클래스를 제공한다. std::functi.. 2015. 7. 21.
4일차 - 지연된 인스턴스화 (lazy instantiation) Intro  아래의 코드가 컴파일이 되지않음은 누구나 쉽게 알 수 있다.void foo (int a) { *a = 10; }int main (int argc, char* argv[]){ return 0;}  그렇다면 다음 코드는 컴파일이 될까?template class A{public: void foo (T a) { *a = 10; }};int main (int argc, char* argv[]){ A a; // a.foo(0); return 0;}  처음의 코드와 별 차이가 없어보이지만 위의 코드는 컴파일이 된다. 왜냐하면 foo는 사용되지 않은 템플릿 함수여서 컴파일러는 foo() 함수에 대한 코드를 생성하지 않기 때문이다. 이렇듯 함수/클래스 템플릿에서 사용되지 않은 부분에 대한 코드를 생성하지 .. 2015. 7. 16.
4일차 - trivial trivial  일반적으로 클래스의 생성자(혹은 복사생성자, 소멸자)가 아무일도 하지 않으면, 이를 trivial하다고 한다. 그럼 '아무 일도 하지않는' 생성자는 정확히 어떤 것을 의미하는 것일까? C++에서는 명시적으로 생성자를 구현하지 않으면 컴파일러가 자동으로 생성자를 만들어준다. 개발자가 생성자를 명시적으로 작성하지 않았다는 것은 기본적으로 생성자에서는 별도의 일을 하지 않겠다는 의미를 담고 있으니, 디폴트 생성자는 trivial하지 않을까라는 생각을 가질 수 있다. 이를 확인하기 위해 아래의 코드를 살펴보자.class A {};class B : public A{public: virtual void foo () {}};  위의 코드에서 클래스 B에는 생성자가 없다. 그러므로 컴파일러는 자동으로.. 2015. 7. 16.