0

これらのコメントを外すと

//BaseList   baselist; 
//MemberList memberlist;

ループの外側で、クラッシュするループの内側のものをコメントアウトします。ベースリスト (およびメンバーリスト) をループの外に置くことができる必要があります。これはどのように達成されますか?

編集

私が最も単純な形で解決しようとしている実際の問題はこれです。

の std::vector がMyClass必要です。これを AllThingsBunchedTogether と呼びます。の std::vector も必要ですBaseList。これを AllThingsSpreadOut と呼びます。

そう

  • AllThingsBunchedTogether には次のものが含まれる場合があります (anInt1コンパクトにするための部分のみ): 1,2,1,10,2,3,4,4,5,9,10,10.
  • AllThingsSpreadOut には、 [1] 1,1at [2] 2,2at [3] 3at [4] 4,4at [5] 5at [9] 9at [10]が含まれている可能性があります (ゼロは今のところ使用されていません) 10,10,10

数値自体は に保存されませんがBaseList、たとえばMyClass(1, "John") に保存されることに注意してください。

[1] では「Mike」、「John」、[2] では「Mike」、「Dagobart」、[3] では「John」、[10] では「John」「Mike」」 Dagobart" などで、BaseListAllThingsSpreadOut[i]のいずれにも重複がないようにします。これはMyClass、それぞれの BaseListハッシュが異なる値になるためです ( anInt1 + Name)。

本質的に、anInt1MyClassAllThingsSpreadOut 内のどこに存在するかを示しますが、anInt1 + name各 内での一意性を保証しますBaseList

つまり、AllThingsSpreadOut は、BaseListBaseListベクトル位置が類似するもののリストであるベクトルであるということです。

次に、AllThingsBunchedTogether から物を削除すると (クリアではなく、以下のコードの IsMarkedToDelete のようにいくつかのアイテムを削除する検索によって)、それらは対応する AllThingsSpreadOut から自動的に消えます。

AllThingsSpreadOut は、押し付けがましいセマンティクスで、AllThingsBunchedTogether の並べ替えとして機能します。AllThingsBunchedTogether は、[] を介した超高速アクセスを可能にします。

編集を終了

#include <vector>
#include <iostream>

#include <boost/intrusive/list.hpp>

using namespace boost::intrusive;

class MyClass : public list_base_hook<link_mode<auto_unlink>> // This is a derivation hook
{
public:
    std::string name;
    bool bIsMarkedToDelete;
    int anInt1;
public:
    list_member_hook<link_mode<auto_unlink>> member_hook_; // This is a member hook

    MyClass(std::string n, int i) : name(n), anInt1(i), bIsMarkedToDelete(false) {}
};

bool IsMarkedToDelete(const MyClass &o)
{
    return o.bIsMarkedToDelete;
}

//Define a list that will store MyClass using the public base hook
typedef list<MyClass, constant_time_size<false>> BaseList;

// Define a list that will store MyClass using the public member hook
typedef list<MyClass,
        member_hook<MyClass, list_member_hook<link_mode<auto_unlink>>, &MyClass::member_hook_>,
        constant_time_size<false> > MemberList;

int main()
{
    bool done = false;
    std::vector<MyClass> values;

    std::string names[] = {"John", "Mike", "Dagobart"};

    //BaseList   baselist; 
    //MemberList memberlist;

    int i = 0;
    while(!done)
    {
        // Create several MyClass objects, each one with a different value

        for (int j = 0; j < 11; ++j)
            values.emplace_back(names[j % 3], j);

        BaseList   baselist;
        MemberList memberlist;

        // Now insert them in t-he reverse order in the base hook list
        for (auto& e : values)
        {
            baselist.push_front(e);
            memberlist.push_back(e);
        }

        // Now test lists
        auto rbit(baselist.rbegin());
        auto mit(memberlist.begin());
        auto it(values.begin()), itend(values.end());

        // Test the objects inserted in the base hook list
        for (; it != itend; ++it, ++rbit)
        {
            if (&*rbit != &*it)
                return 1;
        }
        // Test the objects inserted in the member hook list
        for (it = values.begin(); it != itend; ++it, ++mit)
        {
            if (&*mit != &*it)
                return 1;
        }
# if 0
        for(auto& e : values)
            std::cout << e.anInt1 << "\n";

        for(auto& e : baselist)
            std::cout << e.anInt1 << "\n";

        for(auto& e : memberlist)
            std::cout << e.anInt1 << "\n";

#endif // 0

        if(2 == i)
        {
            for(auto& e: values)
                std::cout << e.name << "\n";

            for(auto& e: values)
            {
                if("Mike" == e.name)
                    e.bIsMarkedToDelete = true;
            }

            values.erase(
                std::remove_if(values.begin(), values.end(), IsMarkedToDelete), values.end());
        }


        if(i++ > 3)
        {
            values.clear();
            done = true;
        }

        std::cout << "\n";
        std::cout << values.size()     << "\n";
        std::cout << baselist.size()   << "\n";
        std::cout << memberlist.size() << "\n";
    }
}
4

2 に答える 2

5

私はそれを遅く見ましたが、とにかく、ここに行きます:

  1. あなたが説明することは、要素の侵入ハッシュテーブルの実装と正確に一致します。MyClass

    • anInt1要素のハッシュ (バケット識別子) です。
    • バケットリストはリンクされたリストとして実装されています
    • 同等性は次の同等性として定義されます(anInt1, Name)

      ここに画像の説明を入力


    つまり、プログラムは次のようになります。

    Live On Coliru

    std::unordered_set<MyClass> 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. 連続したストレージが本当に必要な場合は、パフォーマンスのためにこれが必要だったとしか思えません

    • オブジェクトの代わりにポインターを使用したくない場合は、メモリ レイアウト ("AllThingsBunchedTogether") の利点が無効になるだけであり、上記のunordered_setorを使用した方がよいでしょう。unodered_map

    • モードはパフォーマンスを低下させるため、モードを使用したくありません(制御されていない削除トリガーを実行したり、定数時間を禁止したり、スレッド セーフの問題を作成したりすることによって) 。auto_unlinksize()

    • 代わりに、上記の戦略を採用する必要がありますが、boost::intrusive::unordered_set代わりにhttp://www.boost.org/doc/libs/1_57_0/doc/html/intrusive/unordered_set_unordered_multiset.htmlを参照してください

      繰り返しますが、概念実証は次のとおりです。

      Live On Coliru

      #include <vector>
      #include <iostream>
      #include <boost/intrusive/unordered_set.hpp>
      #include <vector>
      //#include <functional>
      //#include <algorithm>
      
      namespace bic = boost::intrusive;
      
      struct MyClass : bic::unordered_set_base_hook<bic::link_mode<bic::auto_unlink>>
      {
          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<MyClass, bic::hash<MyClass::hasher>, bic::constant_time_size<false> > HashTable;
      
      int main() {
      
          std::vector<MyClass> 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";
      }
      
于 2014-11-11T22:59:03.700 に答える
0

省略したエラーメッセージは次のとおりです。

Assertion `node_algorithms::inited(to_insert)' failed.

このことから、要素が 2 回挿入されていることがわかります。これは一般に、侵入型コンテナーでは有効ではありません。

ループ内にリストがある場合、リストは毎回破棄され、再作成されます。しかし、それらが外にある場合、それらをクリアすることはなく、 もクリアしないvaluesため、次のシーケンスが発生します。

  1. に 11 個の要素を追加しvaluesます。
  2. すべてをリストに追加valuesします。
  3. に 11 個の要素を追加しvaluesます。以前の 11 要素がまだ残っているため、現在は 22 要素です。
  4. すべてをリストに追加valuesします。すでにリストにあるため、最初のものでクラッシュします。

1 つの解決策は、ループvalues.clear()の先頭に追加することです。while(!done)

于 2014-11-11T07:14:05.393 に答える