Trying to learn boost::intrusive Q2

后端 未结 2 435
故里飘歌
故里飘歌 2021-01-17 06:26

if I uncomment these

//BaseList   baselist; 
//MemberList memberlist;

outside the loop and comment out the ones inside the loop it

2条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-01-17 07:15

    I've seen it late, but anyways, here goes:

    1. What you describe matches exactly the implementation of an intrusive hash table of MyClass elements, where

      • anInt1 is the hash (the bucket identifier) for an element
      • the bucket lists are implemented as linked lists
      • equality is defined as equality of (anInt1, Name)

        enter image description here


      So really, your program could just be:

      Live On Coliru

      std::unordered_set values {
          { "John",      0 }, { "Mike",      1 }, { "Dagobart",  2 },
          { "John",      3 }, { "Mike",      4 }, { "Dagobart",  5 },
          { "John",      6 }, { "Mike",      7 }, { "Dagobart",  8 },
          { "John",      9 }, { "Mike",     10 },
      };
      
      for(int i = 0; i<=3; ++i) {
          if(2 == i) {
              for(auto& e: values) std::cout << e.name << " "; std::cout << "\n";
              for(auto& e: values) e.bIsMarkedToDelete |= ("Mike" == e.name);
      
              for(auto it=begin(values); it!=end(values);) {
                  if (it->bIsMarkedToDelete) it = values.erase(it);
                  else ++it;
              }
          }
      
          std::cout << "i=" << i << ", values.size(): " << values.size() << "\n";
      }
      values.clear();
      std::cout << "Done\n";
      
    2. if you really wanted contiguous storage, I can only assume you wanted this for performance

      • you do not want to use pointers instead of objects, since that simply negates the memory layout ("AllThingsBunchedTogether") benefits and you'd be better of with the unordered_set or unodered_map as above

      • you do not want to use auto_unlink mode, since it cripples performance (by doing uncontrolled deletion triggers, by inhibiting constant-time size() and by creating thread safety issues)

      • instead, you should employ the above stratagy, but with boost::intrusive::unordered_set instead see http://www.boost.org/doc/libs/1_57_0/doc/html/intrusive/unordered_set_unordered_multiset.html

        Here, again, is a proof-of-concept:

        Live On Coliru

        #include 
        #include 
        #include 
        #include 
        //#include 
        //#include 
        
        namespace bic = boost::intrusive;
        
        struct MyClass : bic::unordered_set_base_hook>
        {
            std::string name;
            int anInt1;
            mutable bool bIsMarkedToDelete;
        
            MyClass(std::string name, int i) : name(name), anInt1(i), bIsMarkedToDelete(false) {}
        
            bool operator==(MyClass const& o) const { return anInt1 == o.anInt1 && name == o.name; }
        
            struct hasher { size_t operator()(MyClass const& o) const { return o.anInt1; } };
        };
        
        typedef bic::unordered_set, bic::constant_time_size > HashTable;
        
        int main() {
        
            std::vector values {
                MyClass { "John", 0 }, MyClass { "Mike",  1 }, MyClass { "Dagobart", 2 },
                MyClass { "John", 3 }, MyClass { "Mike",  4 }, MyClass { "Dagobart", 5 },
                MyClass { "John", 6 }, MyClass { "Mike",  7 }, MyClass { "Dagobart", 8 },
                MyClass { "John", 9 }, MyClass { "Mike", 10 },
            }; 
        
            HashTable::bucket_type buckets[100];
            HashTable hashtable(values.begin(), values.end(), HashTable::bucket_traits(buckets, 100)); 
        
            for(int i = 0; i<=3; ++i) {
                if(2 == i) {
                    for(auto& e: values) std::cout << e.name << " "; std::cout << "\n";
                    for(auto& e: values) e.bIsMarkedToDelete |= ("Mike" == e.name);
        
                    values.erase(std::remove_if(begin(values), end(values), std::mem_fn(&MyClass::bIsMarkedToDelete)));
                }
        
                std::cout << "i=" << i << ", values.size():    " << values.size()    << "\n";
                std::cout << "i=" << i << ", hashtable.size(): " << hashtable.size() << "\n";
            }
            values.clear();
            std::cout << "Done\n";
        }
        

提交回复
热议问题