몇 번의 편집을 감안할 때 포괄적 인 요약이 유용 할 것이라는 인상을 받았습니다.
1.하지 않을 때
스마트 포인터를 사용해서는 안되는 두 가지 상황이 있습니다.
첫 번째는 C++실제로 클래스를 사용해서는 안되는 똑같은 상황입니다 . IE : 클라이언트에 소스 코드를 제공하지 않는 경우 DLL 경계. 일화를 말해 보자.
두 번째는 훨씬 더 자주 발생합니다. 똑똑한 관리자는 소유권을 의미 합니다. 수명을 관리하지 않고 포인터를 사용하여 기존 리소스를 가리킬 수 있습니다. 예를 들면 다음과 같습니다.
void notowner(const std::string& name)
{
Class* pointer(0);
if (name == "cat")
pointer = getCat();
else if (name == "dog")
pointer = getDog();
if (pointer) doSomething(*pointer);
}
이 예는 제한적입니다. 그러나 포인터는 잘못된 위치 (널 포인터)를 가리킬 수 있다는 점에서 참조와 의미 상 다릅니다. 이 경우 개체의 수명을 관리하고 싶지 않기 때문에 대신 스마트 포인터를 사용하지 않는 것이 좋습니다.
2. 똑똑한 관리자
똑똑한 관리자 클래스를 작성하지 않는 한 키워드 를 사용하면 delete 뭔가 잘못된 것입니다.
논란의 여지가있는 관점이지만 결함이있는 코드의 예를 너무 많이 검토 한 후 더 이상 기회를 잡지 않습니다. 따라서 작성 new하는 경우 새로 할당 된 메모리에 대한 스마트 관리자가 필요합니다. 그리고 지금 당장 필요합니다.
당신이 프로그래머가 아니라는 의미는 아닙니다! 반대로, 작업을 반복하는 대신 작동하는 것으로 입증 된 코드를 재사용하는 것이 핵심 기술입니다.
이제 진정한 어려움이 시작됩니다. 어떤 똑똑한 관리자입니까?
3. 스마트 포인터
다양한 특성을 가진 다양한 스마트 포인터가 있습니다.
std::auto_ptr일반적으로 피해야하는 건너 뛰기 (복사 의미가 잘못됨).
scoped_ptr: 오버 헤드가 없으며 복사하거나 이동할 수 없습니다.
unique_ptr: 오버 헤드 없음, 복사 불가, 이동 가능.
shared_ptr/ weak_ptr: 약간의 오버 헤드 (참조 카운팅), 복사 가능.
일반적으로 scoped_ptr또는 unique_ptr. 여러 명의 소유자가 필요한 경우 디자인을 변경하십시오. 디자인을 변경할 수없고 실제로 여러 명의 소유자가 필요한 경우를 사용 shared_ptr하지만 weak_ptr중간 어딘가에를 사용하여 끊어야하는 참조주기에주의 하세요.
4. 스마트 컨테이너
많은 스마트 포인터는 복사 할 수 없으므로 STL 컨테이너와의 사용이 다소 손상됩니다.
shared_ptr오버 헤드 에 의존하는 대신 Boost Pointer Container 의 스마트 컨테이너를 사용하십시오 . 클래식 STL 컨테이너의 인터페이스를 에뮬레이트하지만 소유 한 포인터를 저장합니다.
5. 나만의 롤링
자신의 스마트 매니저를 롤링하고 싶을 때가 있습니다. 미리 사용중인 라이브러리의 일부 기능을 놓친 것이 아닌지 확인하십시오.
예외가있는 상황에서 똑똑한 관리자를 작성하는 것은 매우 어렵습니다. 당신은 일반적으로 해당 메모리를 사용할 수있는 가정 할 수 없다 ( new실패 할 수 있습니다) 또는 Copy ConstructorS는이 no throw보증을.
std::bad_alloc예외 를 무시하고 Copy Constructor여러 헬퍼 중 s가 실패하지 않도록 강요하는 것이 다소 허용 될 수 있습니다 . 결국, 그것이 boost::shared_ptrdeleter D템플릿 매개 변수에 대해 수행하는 작업입니다.
그러나 특히 초보자에게는 권장하지 않습니다. 까다로운 문제이며 지금 당장은 버그를 눈치 채지 못할 것입니다.
6. 예
using namespace boost;
struct Cloneable
{
virtual ~Cloneable() {}
virtual Cloneable* clone() const = 0;
};
struct Derived: Cloneable
{
virtual Derived* clone() const { new Derived(*this); }
};
void scoped()
{
scoped_ptr<Cloneable> c(new Derived);
}
unique_ptr<Cloneable> unique()
{
return unique_ptr<Cloneable>(new Derived);
}
void shared()
{
shared_ptr<Cloneable> n1(new Derived);
weak_ptr<Cloneable> w = n1;
{
shared_ptr<Cloneable> n2 = n1;
n1.reset();
assert(n1.get() == 0);
assert(n2.get() != 0);
assert(!w.expired() && w.get() != 0);
}
assert(w.expired());
}
void container()
{
ptr_vector<Cloneable> vec;
vec.push_back(new Derived);
vec.push_back(new Derived);
vec.push_back(
vec.front().clone()
);
}