목록 C ++에서 관련 개체 제거

사용자 98

몇 가지 코드가 있습니다.

class LowLevelObject {
    public:
    void* variable;
};

// internal, can't get access, erase, push. just exists somewhere
std::list<LowLevelObject*> low_level_objects_list;


class HighLevelObject {
    public:
    LowLevelObject* low_level_object;
};

// my list of objects
std::list<HighLevelObject*> high_level_objects_list;

// some callback which notifies that LowLevelObject* added to low_level_objects_list.
void CallbackAttachLowLevelObject(LowLevelObject* low_level_object) {
    HighLevelObject* high_level_object = new HighLevelObject;
    high_level_object->low_level_object = low_level_object;
    low_level_object->variable = high_level_object;
    high_level_objects_list.push_back(high_level_object);
}

void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
    // how to delete my HighLevelObject* from high_level_objects_list?
    // HighLevelObject* address in field `variable` of LowLevelObject.
}

라이브러리에 정의 된 저수준 개체가 있으며 variable사용자가 사용할 필드 포함되어 있습니다 .
varaible포인터를 HighLevelObject내 코드에서 설정했습니다 . 라이브러리의 목록에서
추가 및 제거시 콜백을 설정할 수 있습니다 LowLevelObject.
하지만 HighLevelObject내 개체 목록에서 어떻게 제거 할 수 있습니까?
물론 전체 목록을 반복하고 포인터로 개체별로 찾아 제거 할 수 있다는 것을 알고 있지만 먼 길입니다.
목록에는 많은 개체가 포함될 수 있습니다.
미리 감사드립니다!

Jami

설정은 포인터를 반복자로 변환하는 것이 일정한 시간 작업 인 솔루션을 찾는 데 적합합니다. Boost.Intrusive는이 기능을 제공합니다. 그래도 코드를 변경해야합니다. 캡슐화에 대해주의하지 않았다면 이러한 변경 사항이 중요 할 수 있습니다. A boost::intrusive::list는 기능적으로와 유사 std::list하지만 데이터 구조를 약간 변경해야합니다. 이 옵션은 모든 사람에게 적합하지 않을 수 있습니다.

Boost.Intrusive의 또 다른 기능은 때때로 포인터를 반복자로 명시 적으로 변환 할 필요가 없다는 것입니다. 자동 연결 해제를 활성화하면 목록에서 실제 삭제가 소멸자의 뒤에서 발생합니다. 하지만 일정 시간 내에 목록의 크기를 가져와야하는 경우에는 좋은 옵션이 아닙니다. (질문의 어떤 것도 목록의 크기를 가져 오는 것이 필요하다는 것을 나타내지 않으므로이 접근 방식을 계속 진행할 것입니다.)

객체의 컨테이너가있는 경우 침입 목록에 대한 문서를 통해 작업 할 수 있습니다. 그러나 포인터를 사용하면 변환이 잠재적으로 혼란 스러울 수 있으므로 설정을 살펴 보겠습니다. 설정은 다음으로 시작됩니다.

#include <boost/intrusive/list.hpp>

// Shorten the needed boost namespace.
namespace bi = boost::intrusive;

상위 수준 개체 목록에는 포인터가 포함되어 있으므로 보조 구조가 필요합니다. Boost에서 제공하는 클래스에서 파생되는 포인터의 양이 필요합니다. (에서 생성 된 객체가에서 CallbackAttachLowLevelObject()소멸되어야 한다고 가정하겠습니다 CallbackDetachLowLevelObject(). 따라서 원시 포인터를 스마트 포인터로 변경했습니다.)

#include <memory>
#include <utility>

// The auxiliary structure that will be stored in the high level list:
// The hook supplies the intrusive infrastructure.
// The link_mode enables auto-unlinking.
class ListEntry :  public bi::list_base_hook< bi::link_mode<bi::auto_unlink> >
{
public:
    // The expected way to construct this.
    explicit ListEntry(std::unique_ptr<HighLevelObject> && p) : ptr(std::move(p)) {}
    // Another option would be to forward parameters for constructing HighLevelObject,
    // and have the constructor call make_unique. I'll leave that as an exercise.
    
    // Make this class look like a pointer to HighLevelObject.
    const std::unique_ptr<HighLevelObject> & operator->() const { return ptr; }
    HighLevelObject& operator*() const { return *ptr; }

private:
    std::unique_ptr<HighLevelObject> ptr;
};

목록의 정의는 다음과 같습니다. size()자동 연결 해제를 허용하려면 일정하지 않은 시간을 지정해야합니다 .

bi::list<ListEntry, bi::constant_time_size<false>> high_level_objects_list;

이러한 변경을 위해서는 "attach"콜백을 약간 변경해야합니다. "detach"콜백으로 넘어 가기 전에 그것들을 제시하겠습니다.

// Callback that notifies when LowLevelObject* is added to low_level_objects_list.
void CallbackAttachLowLevelObject(LowLevelObject* low_level_object) {
    // Dynamically allocate the entry, in addition to allocating the high level object.
    ListEntry * entry = new ListEntry(std::make_unique<HighLevelObject>());
    (*entry)->low_level_object = low_level_object; // Double indirection needed here.
    low_level_object->variable = entry;
    high_level_objects_list.push_back(*entry);     // Intentional indirection here!
}

이 준비 작업을 통해 RAII에 적합한 것처럼 소멸자에서 정리가 이루어집니다. "분리"는 프로세스를 시작하기 만하면됩니다. 한 줄이면 충분합니다.

void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
    delete static_cast<ListEntry *>(low_level_object->variable);
}

높은 수준의 목록이 개체가 아닌 포인터 인 이유를 설명하기에 충분한 컨텍스트가 (적절하게) 없습니다. 한 가지 잠재적 인 이유는 높은 수준의 개체가 다형성이고 포인터를 사용하면 슬라이싱을 피할 수 있기 때문입니다. 이 경우 (또는 포인터를 사용할 적절한 이유가없는 경우) 기존 코드에 미치는 영향을 줄이면서 침입 목록을 디자인 할 수 있습니다. 여기서주의 할 점 HighLevelObject변경 이 필요하다는 것입니다.

초기 설정은 이전과 동일합니다.

#include <boost/intrusive/list.hpp>

// Shorten the needed boost namespace.
namespace bi = boost::intrusive;

다음으로 HighLevelObject후크에서 파생됩니다.

class HighLevelObject : public bi::list_base_hook< bi::link_mode<bi::auto_unlink> > {
    public:
    LowLevelObject* low_level_object;
};

이 상황에서 목록은 HighLevelObject포인터 나 포인터 스탠드 인이 아닌 s입니다.

bi::list<HighLevelObject, bi::constant_time_size<false>> high_level_objects_list;

"첨부"콜백은 거의 문제의 내용으로 되돌아갑니다. 이 함수의 한 가지 변경 사항은 객체 자체가 포인터가 아니라 목록으로 푸시된다는 것입니다. 이것이 슬라이싱이 문제가되지 않는 이유입니다. 목록에 추가되는 복사본이 아니라 개체 자체입니다.

    high_level_objects_list.push_back(*high_level_object);  // Intentional indirection!

나머지 코드는 그대로 작동 할 수 있습니다. 우리는 다시 한 줄짜리 "분리"콜백이 필요합니다.

void CallbackDetachLowLevelObject(LowLevelObject* low_level_object) {
    delete static_cast<HighLevelObject *>(low_level_object->variable);
}

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

목록 C ++에서 개체 제거

분류에서Dev

C # ASP 세션에 저장된 목록에서 개체 제거

분류에서Dev

목록에서 개체 제거

분류에서Dev

Dart 목록에서 개체 제거

분류에서Dev

웹 링크에 ID 값이없는 경우 c # 목록에서 개체 제거

분류에서Dev

nullptrs를 통해 STD 목록에서 제거 할 C ++ 표시 개체

분류에서Dev

C # LINQ 단일 실행으로 목록에서 여러 개체 제거

분류에서Dev

목록보기에서 xml 채우기와 관련된 C # 문제

분류에서Dev

다른 목록의 목록 기반에서 개체 제거

분류에서Dev

JSON 개체 목록에서 개체 제거

분류에서Dev

다른 개체 목록에서 중복 목록 개체 값을 제거

분류에서Dev

C ++에서 remove 메서드를 사용하여 목록에서 Struct 개체 제거

분류에서Dev

개체 목록에서 특정 항목 제거

분류에서Dev

목록에서 첫 번째 개체 삭제 C #

분류에서Dev

C ++ 목록에서 항목 제거

분류에서Dev

모델의 __str__에서 관련 개체 목록을 가져옵니다.

분류에서Dev

Symfony에서 개체를 삭제할 때 관련된 모든 보안 항목을 제거하는 방법은 무엇입니까?

분류에서Dev

조건에 따라 목록 <개체>에서 중복 제거

분류에서Dev

동시에 목록에서 개체 제거

분류에서Dev

목록 관련 개체 가져 오기

분류에서Dev

C #은 목록 지우기 이벤트 처리기에서 개체를 제거합니다.

분류에서Dev

해당 목록의 foreach 루프에있는 목록에서 개체 제거

분류에서Dev

VB.Net의 목록에서 중복 개체 제거

분류에서Dev

C에서 빈 매개 변수 목록을 void로 지정하는 것과 관련성

분류에서Dev

관련 div에서 체크 박스 목록 만들기

분류에서Dev

Haskell : 목록에서 두 개의 관련 요소 찾기

분류에서Dev

목록에서 개체를 제거 - 목록을 비교 - 문자열이 포함

분류에서Dev

큰 목록을 필터링하여 보조 목록에서 개체 제거

분류에서Dev

GridView C #에서 항목을 클릭하여 ObservableCollection에서 개체 제거

Related 관련 기사

  1. 1

    목록 C ++에서 개체 제거

  2. 2

    C # ASP 세션에 저장된 목록에서 개체 제거

  3. 3

    목록에서 개체 제거

  4. 4

    Dart 목록에서 개체 제거

  5. 5

    웹 링크에 ID 값이없는 경우 c # 목록에서 개체 제거

  6. 6

    nullptrs를 통해 STD 목록에서 제거 할 C ++ 표시 개체

  7. 7

    C # LINQ 단일 실행으로 목록에서 여러 개체 제거

  8. 8

    목록보기에서 xml 채우기와 관련된 C # 문제

  9. 9

    다른 목록의 목록 기반에서 개체 제거

  10. 10

    JSON 개체 목록에서 개체 제거

  11. 11

    다른 개체 목록에서 중복 목록 개체 값을 제거

  12. 12

    C ++에서 remove 메서드를 사용하여 목록에서 Struct 개체 제거

  13. 13

    개체 목록에서 특정 항목 제거

  14. 14

    목록에서 첫 번째 개체 삭제 C #

  15. 15

    C ++ 목록에서 항목 제거

  16. 16

    모델의 __str__에서 관련 개체 목록을 가져옵니다.

  17. 17

    Symfony에서 개체를 삭제할 때 관련된 모든 보안 항목을 제거하는 방법은 무엇입니까?

  18. 18

    조건에 따라 목록 <개체>에서 중복 제거

  19. 19

    동시에 목록에서 개체 제거

  20. 20

    목록 관련 개체 가져 오기

  21. 21

    C #은 목록 지우기 이벤트 처리기에서 개체를 제거합니다.

  22. 22

    해당 목록의 foreach 루프에있는 목록에서 개체 제거

  23. 23

    VB.Net의 목록에서 중복 개체 제거

  24. 24

    C에서 빈 매개 변수 목록을 void로 지정하는 것과 관련성

  25. 25

    관련 div에서 체크 박스 목록 만들기

  26. 26

    Haskell : 목록에서 두 개의 관련 요소 찾기

  27. 27

    목록에서 개체를 제거 - 목록을 비교 - 문자열이 포함

  28. 28

    큰 목록을 필터링하여 보조 목록에서 개체 제거

  29. 29

    GridView C #에서 항목을 클릭하여 ObservableCollection에서 개체 제거

뜨겁다태그

보관