2013-06-29 4 views
4

물론이 문제에 대한 일부 수정 사항을 알고 싶습니다. 그러나 구조 조정이 가능합니다. 의미, 표준 콜렉션 및 시공 시간 이동

그래서 나는 장치에 대한 참조를 저장 다음과 같은 생성자

DeviceDependent(Device& device); 

로, 클래스 DeviceDependent 있습니다. 장치가 상태를 변경할 수 있으므로 해당 장치에 종속적 인 모든 DeviceDependent 인스턴스의 변경이 필요합니다. (짐작할 수 있겠지만이 짐승은 짐승 같은 짐승을 타기위한 것입니다.)

나는 이것을 처리하기 위해 , DeviceDependent::onDeviceLost()의 기능을 가지고 있습니다.

DeviceDependent 인스턴스를 DeviceDependent 생성자에 지정된 장치에 등록 할 계획이었습니다. 기기는 모든 DeviceDependent 인스턴스 중 std::vector<DeviceDependent*> 인스턴스를 이렇게 등록 된 상태로 유지합니다. 그런 다음 해당 벡터를 반복하여 적절할 때 위의 함수를 호출합니다.

이것은 충분히 간단 해 보였습니다. 특히 내가 좋아하는 부분은 코드에서 std::vector<DeviceDependent (or child)>을 가지고 반복적으로 반복 할 수 있다는 점이었습니다. 예를 들어, 클래스 Renderable은 렌더링 할 수있는 객체를 나타내는 이름으로, 적어도 프레임 하나 이상을 반복해야하므로이 객체가 메모리에 흩어져있는 것을 원하지 않았습니다. 나는 고체를 만들 때

내가 이동 의미에 의존 :

사업에 이르기까지, 여기에 문제가 있습니다. 이것은 본질적으로 순전히 내가 큰 물체를 복사하여 std::vector<DeviceDependent (or child)> 컬렉션에 추가하는 것을 고려하지 않았습니다. (여전히 아이디어를 싫어한다.)

그러나 이동 의미론 (그리고 나는 이것을 믿지 않는 사람들을 위해 테스트했다.)에서 객체의 주소가 바뀐다. 기본 생성자가 호출 된 후 더 많이 변경됩니다. 즉, DeviceDependant의 생성자 내 코드는 device.registerDeviceDependent(this)을 컴파일하고 실행하지만 객체는 벡터로 이동하자마자 무효화되는 포인터 목록을 누적한다는 의미입니다.

나는이 계획에 충실하고 효과를 낼 수 있는지 알고 싶습니다. '진짜'벡터 공유 포인터의 수집, 아니 문제 복사를 만들기

  1. :

    내가 생각 것. 개체가 주소를 변경하지 않는 것으로 추정됩니다. 힙에 물건을 두는 것이 반복 성능에 해를 끼칠 까봐 두려워서이 계획이 마음에 들지 않습니다.

  2. 개체가 이동 된 후 등록 정보를 호출하는 것은 임시적으로 수행하는 작업이지만 생성자가이 작업을 수행하기에 적절한 장소라고 생각하기 때문에 마음에 들지 않습니다. 거기에 어떤 장치의 매니 페스트에없는 DeviceDependent의 인스턴스가 없어야합니다.

  3. 내 자신의 이동 생성자를 작성하거나 할당 함수를 이동하십시오. 이렇게하면 장치에서 이전 주소를 제거하고 새 주소로 변경할 수 있습니다. 나는 클래스가 진화하면서 그것을 계속 업데이트하고 싶지 않기 때문에 이것을하고 싶지 않다.

+0

'DeviceDependent'는 디바이스의 종류입니까? 그렇다면, 당신은 단지'Device' 만 가지고 있어야하고 그것은'Device's (이'Device'에 의존하는)를 소유해야합니다. – Aleph

+0

"기본 생성자가 호출 된 후 변경되는 내용은 무엇입니까?" -이 모든 것을 전혀 이해하지 못합니다. 개체가 만들어지면 주소는 ID입니다. 다른 개체에 대해 이야기 할 때만 변경할 수 있습니다. – Xeo

+1

나는 이것이 당신이 요구하고있는 것이 확실하지 않기 때문에 대답으로 글을 올리지는 않을 것이다. 그러나 [당신이 묻고있는 생각을하는 한 가지 방법이있다] (http://ideone.com/GJIjdH) –

답변

1

이것은 이동 생성자와는 아무런 관련이 없습니다. 문제는 std :: vector입니다. 벡터에 새 항목을 추가하면 메모리가 다시 할당되어 모든 DeviceDependant 객체가 벡터 내부의 새 메모리 블록으로 전송됩니다. 그런 다음 각 항목의 새 버전이 생성되고 이전 버전이 삭제됩니다. 공사가 복사 공사인지 이동 공사인지는 관련이 없습니다. 객체는 효과적으로 주소를 변경합니다.

코드를 올바르게 작성하려면 DeviceDependant 객체가 소멸자에서 등록을 취소하고 사본 생성자와 이동 생성자 모두에 등록해야합니다. 이러한 생성자를 삭제하지 않은 경우 저장소에 대한 다른 결정 사항과 상관없이이 작업을 수행해야합니다. 그렇지 않으면 이러한 생성자가 호출되면 잘못된 작업을 수행합니다.

목록에없는 한 가지 방법은 저장할 항목의 최대 수를 지정하여 reserve()를 호출하여 벡터 재 할당을 방지하는 것입니다. 이것은 DeviceDependant 객체의 수에 대한 합리적인 상한을 알고있는 경우에만 실용적입니다. 그러나 벡터 재 할당을 완전히 제거하지 않고 예상 값을 예약하면 미등록 및 재 등록 비용이 중요하지 않은 경우가 거의 없습니다.

DeviceDependants에 대한 캐시 일관성을 얻는 것이 목표 인 것 같습니다. 주 기억 장치로 std :: deque를 사용하면 충분한 캐시 일관성을 유지하면서 재 할당을 피할 수 있습니다. 또는 사용자 정의 할당 자 또는 연산자 new()를 작성하여 캐시 일관성을 확보 할 수 있습니다.

여러분의 디자인이 당신이 추측하고있는 성능 비용에 의해 좌우되는 것처럼 들립니다. 실제로 측정 한 경우 std :: vector>를 사용하면 문제가 없으며 반복 처리에 걸리는 시간이 크게 단축되지는 않습니다. 벡터가 유일한 소유자이기 때문에 여기서 공유 포인터가 필요하지 않으므로 참조 계산의 오버 헤드를 피할 수 있습니다.

+0

당신이 말하는 것은 내가 명시 적으로 사용할지 여부에 관계없이 모든 생성자를 작성하지 못하게하거나 축소해서는 안된다는 것입니다. 나는 성능 문제에 대해 '짐작하고있다'고 생각하지만 그것은 숙련 된 추측이다. DeviceDependnent의 일부 어린이는 상당히 클 것입니다. 나는 수천 명이 될 것을 알고있다. 나는 그들이 여러 번 반복해서 반복해야한다는 것을 안다. 나는 모든 것을 프로 파일링하기 전에 최적화하지 말아야한다는 것을 알고 있지만, 비효율적으로 실행해야한다고 생각하지는 않습니다. –