class Foobar
사용 하는 클래스가 있다고 가정 해보십시오 Widget
. 좋은 시절에는 Widget
wolud를의 필드로 선언 Foobar
하거나 다형성 동작이 필요한 경우 스마트 포인터로 선언 하면 생성자에서 초기화됩니다.
class Foobar {
Widget widget;
public:
Foobar() : widget(blah blah blah) {}
// or
std::unique_ptr<Widget> widget;
public:
Foobar() : widget(std::make_unique<Widget>(blah blah blah)) {}
(…)
};
그리고 우리는 모두 준비되고 끝났습니다. 불행하게도, 오늘날, 자바 어린이들은 우리가 그것을 본 후에, 그리고 합당하게 결합 Foobar
하여 Widget
함께 웃을 것입니다. 해결책은 간단 해 보입니다. 종속성 주입을 적용하여 종속성을 Foobar
클래스 외부로 가져옵니다 . 그러나 C ++은 의존성의 소유권에 대해 생각하도록합니다. 세 가지 솔루션이 떠 오릅니다.
고유 포인터
class Foobar {
std::unique_ptr<Widget> widget;
public:
Foobar(std::unique_ptr<Widget> &&w) : widget(w) {}
(…)
}
Foobar
Widget
그 소유권 만 주장 합니다. 다음과 같은 장점이 있습니다.
- 성능에 미치는 영향은 미미합니다.
Foobar
수명이 길어질수록 안전Widget
하므로Widget
갑자기 사라지지 않습니다.Widget
누출되지 않으며 더 이상 필요하지 않을 때 올바르게 파괴되는 것이 안전 합니다.
그러나 이것은 비용이 듭니다 :
Widget
예를 들어 스택 할당을Widgets
사용할 수없고,Widget
공유 할 수 없는 것과 같이 인스턴스 사용 방법에 제한 이 있습니다.
공유 포인터
class Foobar {
std::shared_ptr<Widget> widget;
public:
Foobar(const std::shared_ptr<Widget> &w) : widget(w) {}
(…)
}
이것은 아마도 Java 및 기타 가비지 수집 언어와 가장 비슷합니다. 장점 :
- 종속성을 공유 할 수 있으므로보다 보편적입니다.
unique_ptr
솔루션의 안전 (2 및 3 지점)을 유지 합니다.
단점 :
- 공유가 포함되지 않으면 리소스를 낭비합니다.
- 여전히 힙 할당이 필요하며 스택 할당 객체를 허용하지 않습니다.
평범한 관찰 포인터
class Foobar {
Widget *widget;
public:
Foobar(Widget *w) : widget(w) {}
(…)
}
수업 중에 생생한 포인터를 놓고 소유의 부담을 다른 사람에게 이전하십시오. 장점 :
- 최대한 간단합니다.
- 유니버설, 그냥 받아 들인다
Widget
.
단점 :
- 더 이상 안전하지 않습니다.
Foobar
및의 소유권을 담당하는 다른 엔터티를 소개Widget
합니다.
미친 템플릿 메타 프로그래밍
내가 생각할 수있는 유일한 장점은 소프트웨어가 구축되는 동안 내가 찾지 못한 모든 책을 읽을 수 있다는 것입니다.)
가장 보편적 Foobars
이므로 어쨌든 무언가를 관리해야 하므로 관리 Widgets
는 간단한 변화입니다. 그러나 원시 포인터를 사용하면 나를 귀찮게 할 수 있습니다. 반면에 스마트 포인터 솔루션은 종속성 소비자가 종속성 생성 방법을 제한하므로 나에게 잘못된 느낌을줍니다.
뭔가 빠졌습니까? 아니면 C ++의 의존성 주입이 사소하지 않습니까? 클래스가 의존성을 소유해야합니까 아니면 그냥 관찰해야합니까?
Foobar
이것이 유일한 소유자 인지 어떻게 알 수 있습니까? 오래된 경우에는 간단합니다. 그러나 DI의 문제점은 클래스가 종속성 구성에서 분리 될 때 클래스가 종속성의 소유권에서 분리되는 것입니다 (소유가 건설과 관련되어 있기 때문에). Java와 같은 가비지 수집 환경에서는 문제가되지 않습니다. C ++에서 이것은입니다.
std::unique_ptr
갈 수있는 방법입니다.std::move()
자원 소유권을 상위 범위에서 클래스로 이전하는 데 사용할 수 있습니다 .