일반 클래스 라이브러리 - 버그, 설명, 질문, 사용 기능 및 제안 사항 - 페이지 29

 
Alexey Volchanskiy :

MSDN에서는 링 버퍼라고 하는데 이름이 떠오르지 않네요.

스튜디오 링크

알렉세이 나보이코프 :

...그리고 값이 아니라 참조에 의한 인수 재작업으로 끝납니다.

리터럴에 문제가 있을 수 있습니다

 
TheXpert :

스튜디오 링크

리터럴에 문제가 있을 수 있습니다

그 기사를 다시 찾기에는 너무 게으르지만 조금 망쳤습니다. 고리 모양의 하나 또는 두 개의 연결 목록은 연결 목록을 기반으로 작성되지만 맨 처음에 대한 링크는 마지막 요소에 저장됩니다.

 
TheXpert :

리터럴에 문제가 있을 수 있습니다

예, 아니요, 내 클래스 "값"은 순수하게 래퍼로서 기본 클래스 "참조"에서 상속됩니다. 따라서 클래스의 필요한 버전을 선택하기만 하면 됩니다.
 
Alexey Volchanskiy :

순환형 1 또는 2 연결 목록은 연결 목록을 기반으로 작성되지만 맨 처음에 대한 링크는 마지막 요소에 저장됩니다.

따라서 문제의 사실은 그것이 대가가 아니라 "기본"으로 구축된다는 것입니다. 아무도 개발자가 추가 컨테이너로 이 작업을 수행하는 것을 막지 못했습니다. 기존의 지혜를 바꾸지 마십시오
 
Alexey Navoykov :

아마도 이러한 클래스를 이식한 사람은 코드를 단순화하여 자신의 삶을 더 쉽게 만들기로 결정했을 것입니다. 두 개의 포인터 m_first와 m_last 대신, 하나의 포인터 m_head를 만들었습니다.

dotnet 소스를 보고 그 이유를 이해했습니다. LinkedList 클래스 자체는 올바르게 이식되었으며 실제로는 시작과 끝을 나타내는 헤드 포인터가 하나만 있습니다. 저것들. 내부 구현은 실제로 루프됩니다. 그러나 외부 행동은 그렇지 않습니다. MQ의 CLinkedNode 클래스(Next 및 Previous 메서드)에 오류가 있습니다. 원래 구현은 다음과 같습니다.

         public LinkedListNode<T>? Next
        {
             get { return next == null || next == list!.head ? null : next; }
        }

         public LinkedListNode<T>? Previous
        {
             get { return prev == null || this == list!.head ? null : prev; }
        }

MQL로 포팅되는 방법은 다음과 같습니다.

   CLinkedListNode<T>* Next( void )                      { return (m_next); }
   CLinkedListNode<T>* Previous( void )                  { return (m_prev); }

아마도 무심코 섞였을 것입니다.

그러나 일반적으로 dotnet에서의 구현에 대해서도 약간 놀랐습니다. 하나의 헤드 대신 목록 자체(첫 번째와 마지막)에 두 개의 포인터를 만들지 않는 이유는 무엇입니까? 이렇게 하면 위의 목록 노드 방법에서 불필요한 검사를 피할 수 있습니다. 지금은 MQ처럼 보이지만 모든 것이 올바르게 작동합니다. 물론 이렇게 하면 노드 삽입/삭제 프로세스가 약간 느려지지만 훨씬 더 우선시되는 노드에 대한 반복 속도가 크게 빨라집니다. Next 및 Previous는 의심할 여지 없이 노드가 추가되는 것보다 더 자주 호출됩니다. 나는 나 자신을 위해 그것을했고, 작고 부드러운 것들도 비슷할 것이라고 생각했습니다. 어쨌든 )

그건 그렇고, MQ에는 CLinkedListNode 및 CRedBlackTreeNode의 구현에 하나 이상의 잼이 있습니다. m_next, m_prev 등의 필드(m_value 제외)는 목록 클래스 자체에 의해 독점적으로 변경됩니다. 다른 사람이 변경해서는 안 됩니다. 따라서 dotnet에서는 내부 필드입니다. 사용자는 get 메소드만 사용할 수 있습니다. 그리고 어떤 이유에서인지 MQ는 이러한 필드를 변경하기 위한 공개 메서드를 만들었습니다. 적어도 이름을 구체적으로 지정하면 좋을 것입니다. 하지만 일반적인 이름은 아닙니다.

 void               Next(CLinkedListNode<T>* value )     { m_next= value ; }
 

안녕하세요!

CopyTo를 사용하고 수동으로 삭제하는 것 외에 CHashMap에서 요소를 삭제하는 다른 방법이 있습니까?

 

다음은 라이브러리 구현 곡선의 용광로에 몇 가지 장작이 더 있습니다. 어떤 이유로 해당 CKeyValuePair 클래스는 IComparable 인터페이스(및 그에 따라 IEqualityComparable)를 상속하므로 사용자 지정 키 형식도 이러한 인터페이스를 지원해야 합니다. 우리가 우리 자신의 Comparer를 정의한다면 이것은 필요하지 않지만. 물론 원래 KeyValuePair에는 인터페이스가 없습니다.

계속 파고들면 더 이상한 것을 발견하게 됩니다.

 template < typename TKey, typename TVal>
CHashMap::CHashMap(IEqualityComparer<TKey>*comparer): m_count( 0 ),
                                                      m_free_list( 0 ),
                                                      m_free_count( 0 ),
                                                      m_capacity( 0 )
  {
//--- check equality comaprer
   if ( CheckPointer (comparer)== POINTER_INVALID )
     {
       //--- use default equality comaprer    
      m_comparer= new CDefaultEqualityComparer<TKey>();
      m_delete_comparer= true ;
     }
   else
     {
       //--- use specified equality comaprer
      m_comparer=comparer;
      m_delete_comparer= false ;
     }
  }

저것들. 실수로 깨진 포인터를 생성자에 전달하면 프로그램이 계속 조용히 작동할 뿐만 아니라 논리도 변경됩니다! 응...

생성자는 다음과 같아야 합니다.

 template < typename TKey, typename TVal>
CHashMap::CHashMap(IEqualityComparer <TKey> *comparer): m_count( 0 ),
                                                      m_free_list( 0 ),
                                                      m_free_count( 0 ),
                                                      m_capacity( 0 ),
                                                      m_comparer(comparer),
                                                      m_delete_comparer( false )
{ }

그리고 POINTER_INVALID 가 없습니다. 그리고 기본 비교자의 경우 또 다른 생성자 서명이 있습니다.

 
임의의 클래스를 T 매개 변수로 사용 하여 CQueue<T> 템플릿을 올바르게 적용하는 방법의 예가 있습니까?
 
이미 병렬 스레드에 있습니다. 금지를 요청합니다.
 

코드가 컴파일되지 않는 이유를 말씀해 주시겠습니까?

 #include <Generic\HashMap.mqh>
void OnStart ()
  {
   CHashMap< ENUM_CHART_PROPERTY_INTEGER , int > mapI;     // эта срока компилируется без ошибок
   CHashMap< ENUM_CHART_PROPERTY_DOUBLE , double > mapD;   // здесь ошибки компиляции: 'NULL' - cannot convert enum  HashMap.mqh     21      39. 'NULL' - cannot convert enum        HashMap.mqh     462     30
   CHashMap< ENUM_CHART_PROPERTY_STRING , string > mapS;   // здесь ошибки компиляции: 'NULL' - cannot convert enum  HashMap.mqh     21      39. 'NULL' - cannot convert enum        HashMap.mqh     462     30

  }

문제는 시스템 열거형에 있습니다. ENUM_CHART_PROPERTY_DOUBLE, ENUM_CHART_PROPERTY_STRING에 문제가 있습니다. 고유한 열거형을 키 유형으로 사용하는 경우 컴파일   통과.