shared_ptr
파생 유형을 shared_ptr
기본 유형 을 취하는 함수 에 전달하는 가장 좋은 방법은 무엇입니까 ?
나는 일반적으로 shared_ptr
불필요한 사본을 피하기 위해 s를 참조로 전달합니다 .
int foo(const shared_ptr<bar>& ptr);
하지만 다음과 같은 작업을 시도하면 작동하지 않습니다.
int foo(const shared_ptr<Base>& ptr);
...
shared_ptr<Derived> bar = make_shared<Derived>();
foo(bar);
나는 사용할 수있다
foo(dynamic_pointer_cast<Base, Derived>(bar));
그러나 이것은 두 가지 이유로 차선책으로 보입니다.
- A
dynamic_cast
는 단순한 파생에서 기본 캐스트에 대해 약간 과도하게 보입니다. - 내가 이해했듯이
dynamic_pointer_cast
함수에 전달할 포인터의 복사본 (임시적이긴하지만)을 만듭니다.
더 나은 해결책이 있습니까?
후손을위한 업데이트 :
누락 된 헤더 파일 문제로 판명되었습니다. 또한 여기서 제가하려는 것은 반 패턴으로 간주됩니다. 일반적으로,
-
객체의 수명에 영향을주지 않는 함수 (즉, 객체가 함수 기간 동안 유효 함)는 일반 참조 또는 포인터를 가져야합니다 (예 :
int foo(bar& b)
. -
객체 를 소비 하는 함수 (즉, 주어진 객체의 최종 사용자)는
unique_ptr
값 (예 :)을 가져야합니다int foo(unique_ptr<bar> b)
. 호출자는std::move
함수에 값을 입력해야합니다. -
객체의 수명을 연장하는 함수는
shared_ptr
예를 들어int foo(shared_ptr<bar> b)
. 순환 참조 를 피하기위한 일반적인 조언이 적용됩니다.
자세한 내용은 Herb Sutter의 Back to Basics 토크 를 참조하십시오.
답변
Base
및 Derived
공변 이더라도 그들에 대한 원시 포인터는 그에 따라 작동 shared_ptr<Base>
하며 공변 shared_ptr<Derived>
이 아닙니다 . 는 dynamic_pointer_cast
이 문제를 처리 할 수있는 정확하고 간단한 방법입니다.
( 편집 : static_pointer_cast
파생에서 기본으로 캐스팅하므로 안전하고 런타임 검사가 필요하지 않으므로 더 적합합니다. 아래 주석을 참조하십시오.)
그러나 foo()
함수가 수명 연장에 참여하지 않으려는 경우 (또는 객체의 공유 소유권에 참여하는 대신) 를 전달할 때 를 수락 const Base&
하고 역 참조하는 것이 가장 좋습니다 .shared_ptr
foo()
void foo(const Base& base);
[...]
shared_ptr<Derived> spDerived = getDerived();
foo(*spDerived);
제쳐두고, shared_ptr
유형은 공변이 될 수 없기 때문에 공변 반환 유형에 대한 암시 적 변환 규칙은의 유형을 반환 할 때 적용되지 않습니다 shared_ptr<T>
.
답변
파생 클래스에 대해 공용 상속 을 지정하는 것을 잊은 경우에도 마찬가지입니다. 즉, 저처럼 다음과 같이 작성합니다.
class Derived : Base
{
};
답변
너무 열심히 노력하는 것 같습니다. shared_ptr
복사하기가 저렴합니다. 그것이 목표 중 하나입니다. 참조로 전달하는 것은 실제로 많은 것을 성취하지 못합니다. 공유하지 않으려면 원시 포인터를 전달하십시오.
즉, 머리 위에서 생각할 수있는 두 가지 방법이 있습니다.
foo(shared_ptr<Base>(bar));
foo(static_pointer_cast<Base>(bar));
답변
또한 #include
파생 클래스의 전체 선언을 포함하는 헤더 파일의가 소스 파일에 있는지 확인하십시오.
나는이 문제가 있었다. 은 std::shared<derived>
에 캐스팅 않을 것이다 std::shared<base>
. 나는 그들에 대한 포인터를 보유 할 수 있도록 두 클래스를 앞으로 선언했지만 #include
컴파일러가 없었기 때문에 한 클래스가 다른 클래스에서 파생되었음을 알 수 없었습니다.