지난 1 시간 동안이 코드에 갇혀 있었지만 여전히 스마트 포인터를 머리에 쓰고 구현하려고했지만이 문제로 인해 꽤 어려움을 겪었습니다.문제 전달 std :: unique_ptr의
내가 듣고있는 오류 메시지는 다음과 같습니다.
'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
지난 1 시간 동안이 코드에 갇혀 있었지만 여전히 스마트 포인터를 머리에 쓰고 구현하려고했지만이 문제로 인해 꽤 어려움을 겪었습니다.문제 전달 std :: unique_ptr의
내가 듣고있는 오류 메시지는 다음과 같습니다.
'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
값으로 unique_ptr
을 전달할 수 없습니다. 금지 된 unique_ptr
의 복사본을 만들려고 다음과 같습니다
if(gameObject->isCollidable()){
_actors.Add(gameObject); // THIS LINE
} else {
_props.Add(gameObject); // and THIS LINE
}
해결책이 std::move()
으로 전달하고이 두 개의 소유권 이전에 발생합니다
if(gameObject->isCollidable()){
_actors.Add(std::move(gameObject));
// ^^^^^^^^^
} else {
_props.Add(std::move(gameObject));
// ^^^^^^^^^
}
. 하나는 의 입력 매개 변수이고 std::pair
의 하나는 _gameObjects
인 std::unique_ptr<Entity>
입니다.
GameObjectManager::Add
의 서명을 수정하는 것입니다
: 현재하고있는 것처럼 이제
void GameObjectManager::Add(std::unique_ptr<Entity> & gameObject)
// ^^^
, 당신은 메서드를 호출 할 수 있습니다, 이것은에 (단일 소유권 이전에 발생합니다 pair
in _gameObjects
).
그러나 주석에서 @Xeo가 지적한대로 두 번째 옵션은 우수 사례 원칙을 위반합니다. 소유권 이전은 모든 지점에 명시되어야합니다.
당신은 std::move
를 사용하여 Add
에 addEntity
에서 소유권을 전달해야합니다 : 당신은 명시 적으로는 이동할 수 있도록없이 unique_ptr
를 전달할 수 없습니다
if(gameObject->isCollidable()){
_actors.Add(std::move(gameObject));
} else {
_props.Add(std::move(gameObject));
}
. 이것이이 포인터를 고유 포인터로 만드는 이유입니다. 복사 할 수 있으면 원본과 복사본이 같은 개체를 가리키고 있습니다. 그것으로부터 이동할 때, 원래 포인터는 새로운 포인터에 소유권을 포기합니다.
그리고 명시 적으로 이동을 허용하면 더 이상 복사되지 않습니다. P – Xeo
아, 끝내 주네! 수정 해 주셔서 감사합니다! – user1725794
@Xeo 좋은 지적! –
당신은받는 함수에 unique_ptr
좌변을 통과하려고되어 그 포인터의 사본를 만드는 초래 값에 의해 unique_ptr
이 의도적으로 금지되어 있습니다. 고유 포인터는 고유 한 소유권을 모델링하기위한 것입니다. 이는 고유 포인터를 보유하는 엔티티가 뾰족한 객체의 소유권을 가짐을 의미합니다.
고유 한 포인터를 주위에 복사하는 것은 시스템 전체에 여러 개의 소유 포인터가 퍼져있는 것을 의미합니다. 물론 고유 한 포인터의 고유 한 목적을 상실하게되는 것은 물론 고유 포인터를 복사 할 수없는 이유를 설명합니다.
당신이 할 수있는 것은 이전이 소유하는 것입니다, 그래서 당신은 그 함수에 인수로 전달 할 때, 당신은 할 수 이동unique_ptr
고유 포인터를 허용하는 함수를 호출하는 경우 :
_actors.Add(std::move(gameObject));
// ^^^^^^^^^
으로 소유권을 이전하면이 고유 한 포인터에서 사라진다는 것은 이전에 가리킨 대상을 소유하지 않은 "좀비"고유 포인터 개체가 호출자 기능에 남아 있음을 의미하므로 호출자 함수는 더 이상 참조를 취소하려고하지 마십시오.
소유권 이전은 모든 지점에서 명시되어야합니다. – Xeo
Xeo를 어떻게 사용합니까? 참조 방법을 사용하는 것이 나쁜 progrmaming일까요? – user1725794
@ user1725794 : 미묘합니다. 고유 포인터의 소유권 이전은 항상 명시 적이어야합니다. 이 방법으로 고유 한 포인터를 공유하는 두 개의 루틴으로 끝나며, 어떤 종류의 'unique_ptr'(즉, 한 번에 * one * 엔티티에 의해 소유되어야 함)의 목적을 무효화합니다. Btw, 일부 사용자에게 알리려면 사용자 이름 앞에'@'문자를 사용해야합니다. –