본문 바로가기

Effective C++/3. 자원 관리

(4)
항목 17: new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자. 처리 우선순위를 알려 주는 함수가 하나 있고, 동적으로 할당된 Widget 객체(자원)에 대해 어떤 우선순위에 따라 처리를 적용하는 함수가 하나 있다고 가정해보자. 자원 관리에는 자원 관리 객체를 사용하는 것이 좋다 => Widget 객체에 대해 스마트 포인터를 사용하도록 만들었다. 이렇게 만들어진 processWidget을 호출해보자. tr1::shared_ptr의 생성자는 explicit으로 되어있기 때문에, 암시적 형 변환이 일어나지 않는다. 그래서 명시적 변환을 해줘야 한다. 이제 컴파일은 잘 되지만, 이 문장은 자원을 흘릴 가능성이 있다.(아니 자원 관리 객체를 쓰는데도 왜 자원이 샘?) 일단 첫번째 인자는 크게 두 개로 나눠어져 있음 "new Widget" 표현식을 쓰는 부분 tr1::shar..
항목 16: new 및 delete를 사용할 때는 형태를 반드시 맞추자. std::string *stringArray = new std::string[100]; … delete stringArray; 여기서 잘못된 점이 보이냐? => 이 프로그램은 무조건 미정의 동작을 한다. 왜 why => stringArray가 가르키는 100개의 string 객체 중에 99개는 제대로 소멸 과정을 거치지 못할 것이기 때문이다. 우리가 new 연산자를 사용해서 표현식을 꾸미게 되면(즉, new로 어떤 객체를 동적 할당하면), 두 가지의 내부 동작이 진행된다. 메모리가 할당된다. 할당된 메모리에 대해 한 개 이상의 생성자가 호출된다. delete 표현식을 쓸 경우에는 기존에 할당된 메모리에 대해 한 개 이상의 소멸자가 호출된다. 메모리가 해제된다.(이때 operator delete라는 이름의..
항목 15: 자원 관리 클래스에서 관리하는 자원은 외부에서 접근할 수 있도록 하자 자원 관리 클래스 == good class 실수로 터질 수 있는 자원 누출은 튼튼히 막아 주는 보호벽 역할을 한다. 똑바로 설계된 시스템이면 당연히 자원 누출은 없어야 한다. 하지만 세상은 만만치 않다. 현장에서 열심히 쓰이고 있는 수많은 API들이 자원을 직접 참조하도록 되있어서, 자원 관리 객체를 넘어가서 직접 자원을 주물러야 하는 일이 있을 수 밖에 없다… 우리는 dayHeld를 다음과 같이 쓰고 싶은데 타입이 안맞음 타입을 맞추는 방법 : 명시적, 암시적 반환 명시적: RAII 클래스(shared_ptr)는 get() 이라는 함수를 제공함, 이 함수를 사용하면 각 타입으로 만든 스마트 포인터 객체에 들어 있는 실제 포인터(의 사본)을 얻을 수 있다. 암시적: 제대로된 스마트 포인터들은 다 역참조 ..
항목 13: 자원 관리에는 객체가 그만! 만약 투자를 모델링 해주는 클래스 라이브러리를 가지고 어떤 작업을 한다고 생각해보자. 이 라이브러리는 Investment라는 최상위 클래스가 있고. 이것을 기본으로 구체적인 형태의 투자 클래스가 파생되어 있다. 또 이 라이브러리는 Investment에서 파생된 클래스의 객체를 사용자가 얻어내는 용도로 팩토리 함수(항목 7 참조)만을 쓰도록 만들어져 있다고 해보자. 객체의 해제는 사용자가 직접 해야 한다고 가정하면, 저렇게 delete pInv;를 할 것인데 당연히 f가 실행되면 delete문이 실행될 것이라고 믿으면 안됨 처음엔 무조건 delete문으로 코드가 흐르게 잘 해놨어도, 유지보수를 하면서 멍청한 다른 프로그래머가 continue와 return을 남발한다던지 해서 이 흐름을 박살냈을 수도 있다...