2016-10-31 3 views
0

최적화 (Animal에서 Dog 상속)을, 그리고 당신은 종종 동물을 기대하지만, 강아지의 인스턴스를 보내는 상황이 AnimalDog. 필자의 특별한 경우에는 동물성 기대 함수 (std::shared_ptr<Animal>)에 강한 포인터 (std::shared_ptr<Dog>)를 던지기도합니다.C++ reinterpret_cast 당신은 두 개의 클래스가

함수 매개 변수를 참조 (std::shared_ptr<Animal>&, 스레드와 소유권 변경에 대한 우려로 인해 참조 포인터로 사용하지 않아야하는 이유에 대한 논증을 피할 수 있음)을 받아 들인다면 안전한 메모리라고 가정합니다. 을 사용하여 std::shared_ptr<Dog> dog을 전송하려면 오른쪽을 클릭하십시오.

그렇다면 스레딩 문제 이외의 문제는 무엇이있을 수 있습니까? 참조 횟수 다양성과 같은

분명히 말하자면, 한 번 주조하는 것이 실제로 가능한 솔루션이 아닌 많은 경우에 사용되는 솔루션을 얻는 것이 목적입니다. 그것은 던져 져야 할 많은 객체가 있다는 것이 더 많은 이슈입니다. 또한 그 것을 무시하면 std::unique_ptr이 더 나은 해결책 일 수도 있고 아닐 수도 있습니다. 제가 가상있는 일반화 된 시리얼 클래스 함수의 경우 원래 std::shared_ptr을 변경할 수 없습니다 것입니다 일반 포인터를 사용하여 템플릿을 할 수 없습니다 -

최종 요구 사항을 추가합니다.

+0

왜 ['static_pointer_cast'] (http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast)를 사용하지 않습니까? – krzaq

+0

오버 헤드를 피하려면. 내 특별한 경우에, 이것은 코드가 생성되는 곳입니다. 또는 상속의 여러 계층이 있고 위쪽으로 계속 캐스팅해야하는 사용자 지정 복사본 생성자를 만드는 경우 –

+0

이 클래스는 상속과 관련이 있습니까? – Steve

답변

0

나는 종종 동물 기대 기능 (std::shared_ptr<Animal>)에 강한 포인터 (std::shared_ptr<Dog>)를 주조하고 있습니다.

변환 할 필요가 없습니다. 즉, 명시 적으로로 변환하십시오. 파생 형식에 대한 공유 포인터는 암시 적으로 기본 클래스에 대한 공유 포인터로 변환 (1)됩니다.

의 (a) 우리는 몇 가지 요구 사항이 충족되면 우리는 우리는이 가정을 받아 들일 수있는 함수 매개 변수를 참조

을 할 수 있음을 동의합니다. 첫째, 함수는 함수의 범위를 벗어나는 참조 된 인수를 저장해서는 안됩니다 (복사 제외). 둘째, 참조로 전달 된 포인터는 로컬 또는 임시이어야합니다. 그렇지 않은 경우 함수는 참조 된 포인터에 직접 또는 간접적으로 액세스 할 수있는 함수를 호출하면 안됩니다.

또한 참조가 비 const 인 경우 암시 적 변환 (1)에 의존 할 수 없다고 생각하십시오. 대신 올바른 유형의 별도 공유 포인터를 만들어야합니다 (암시 적 변환을 사용하여이를 생성하고 전달할 수 있습니다.) const 참조 인수 또는 참조가 아닌 인수에는 해당 문제가 없습니다.

) 내가 바로, 우리가 안전 메모리 현명한 reinterpret_cast<std::shared_ptr<Animal>&>(dog)를 사용하여 표준 : : shared_ptr의 개를 주조하는 것입니다 가정

표준 현명한 당신의 제안 캐스트는 안전하지 않습니다 -.이 동작을 보증되지 나는 보지 않는다 가정 (b)가 가정 (a)에서 어떻게 나오는지.그것은 귀하의 경우 인수로 shared_ptr는 참조를 사용하는 것이 괜찮지 만 당신이 때문에 변환에 refcounter의 증가/감소를 피할 수없는 경우


(베이스에서 const const가 아닌에 파생), 내가 사용하는 것이 좋습니다 대신 인수에 대한 포인터.

+0

당신은 단지 일반 포인터를 사용하여 귀하의 제안은 아마 내가 가지고있는 사용자 정의 복사 생성자를 처리 할 수 ​​있습니다. 그러나 베어 포인터를 사용하는 한가지 주의점은 원래'std :: shared_ptr' 자체를 수정할 수 없다는 것입니다. 예를 들어, 변수를 변경해야하는 일반화 된'Serialize()'메소드가 있고 가상 메소드가 필요하기 때문에 메소드 자체를 템플릿화할 수 없습니다. –

+0

당신은 아마도 맨손으로 포인터를 전달할 수 있고, 당신이 할당 된 베어러 포인터를 리턴 할 수있다. (파생 된 타입의 공유 포인터를 받아 들일 수없는 함수는 반드시 파생 된 포인터를 반환 할 수 없기 때문에 다운 캐스팅 후에 shared_ptr에 할당한다. – user2079303

관련 문제