2017-05-15 1 views
1

私はJavaのバックグラウンドから来ています。 (ハッシュ)マップとセットは、私が仕事の過程で毎日扱うものです。 C++(または手動で管理される一般的なメモリ)に関しては、正しく動作させる方法を知っています。C++はメモリ管理をJavaの観点から設定します。

定義により、オブジェクトをセット/マップに追加するときに、識別子/識別子がまだ存在しない場合にのみ追加されます。したがって、Add()/Put()を呼び出す関数は、オブジェクトが追加された後にオブジェクトを破棄してはならない(または破損したポインタがセット内に残っている)場合、オブジェクトがセット内で見つかったためにオブジェクトが追加されなかった場合は破壊する必要がありますリークがそこにあります)、追加しようとしたオブジェクトと同じオブジェクトがセット内に見つかった場合、それを破壊してはなりません。私の場合、データオブジェクトが再帰的に依存する可能性があるため、ディープコピーを作成することは実際には不可能です(または私はどのように明確ではありません)。

セットからサブセットを取得するとき(foosとbarを含むセットのすべてのバーを言います)、オリジナルセットの割り当てを解除すると、すべてのfoosを解放する必要があります。サブセットに含まれるバーは解放してはいけません。セットが解放された場合には解放されなければなりませんが、他のセットで使用されなくなった場合に限り解放されなければなりません。長い棒のセットがオリジナルのセットからも派生し、棒のセットがおそらく別のスレッドでもわからない場合はどうなりますか?

この問題を説明するために、メモリ内のリンクされたデータの小さなレコードを管理するJavaの最小限の例を示します。以下のmain()メソッドは、そのユースケースの可能性のいくつかを示しています。

interface IObject { } 

interface INode extends IObject { } 

interface IIdentifiable extends IObject { 
    String m_csSubject(); 
} 

class CLiteral implements IObject { 
    private String m_csValue; 
    CLiteral(String csValue) { m_csValue = csValue; } 
    String m_csValue() { return m_csValue; } 

    public int hashCode() { 
     return 31 * 1 + ((m_csValue == null) ? 0 : m_csValue.hashCode()); 
    } 

    public boolean equals(Object cObject) { 
     if (this == cObject) return true; 
     if (cObject == null) return false; 
     if (getClass() != cObject.getClass()) return false; 
     CLiteral cOther = (CLiteral) cObject; 
     if (m_csValue == null) { 
      if (cOther.m_csValue != null) return false; 
     } else if (!m_csValue.equals(cOther.m_csValue)) return false; 
     return true; 
    } 
} 

class CLangString extends CLiteral { 
    private final String m_csLanguage; 
    CLangString(String csValue, String csLanguage) { 
     super(csValue); 
     m_csLanguage = csLanguage; 
    } 

    public int hashCode() { 
     return 31 * super.hashCode() + ((m_csLanguage == null) ? 0 : m_csLanguage.hashCode()); 
    } 

    public boolean equals(Object cObject) { 
     if (this == cObject) return true; 
     if (!super.equals(cObject)) return false; 
     if (getClass() != cObject.getClass()) return false; 
     CLangString cOther = (CLangString) cObject; 
     if (m_csLanguage == null) { 
      if (cOther.m_csLanguage != null) return false; 
     } else if (!m_csLanguage.equals(cOther.m_csLanguage)) return false; 
     return true; 
    } 
} 

class CLink implements IIdentifiable, INode { 
    private String m_csSubject; 

    CLink(String csSubject) { m_csSubject = csSubject; } 
    public String m_csSubject() { return m_csSubject; } 

    public int hashCode() { 
     return 31 * 1 + ((m_csSubject == null) ? 0 : m_csSubject.hashCode()); 
    } 

    public boolean equals(Object cObject) { 
     if (this == cObject) return true; 
     if (cObject == null) return false; 
     if (getClass() != cObject.getClass()) return false; 
     CLink cOther = (CLink) cObject; 
     if (m_csSubject == null) { 
      if (cOther.m_csSubject != null) return false; 
     } else if (!m_csSubject.equals(cOther.m_csSubject)) return false; 
     return true; 
    } 
} 

import java.util.*; 
import java.util.Map.Entry; 
class CNode implements INode { 
    static final String m_csTYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"; 
    final Map<String, Collection<IObject>> m_cEdges = new HashMap<>(); 

    CNode() { } 
    CNode(CLink cType) { put(m_csTYPE, cType); } 
    CNode(String csType) { this(new CLink(csType)); } 

    CResult get(String csPredicate) { 
     CResult cResult = new CResult(); 
     cResult.addAll(m_cEdges.get(csPredicate)); 
     return cResult; 
    } 

    CResult getById(String csPredicate, String csIdPredicate, String csIdValue) { 
     CResult cResult = new CResult(); 
     for (Entry<String, Collection<IObject>> cEntry : m_cEdges.entrySet()) 
      for (IObject cValue : cEntry.getValue()) 
       if (cValue instanceof CNode) { 
        CNode cNode = (CNode) cValue; 
        if (cNode.hasType(csPredicate) && cNode.get(csIdPredicate).Strings().contains(csIdValue)) 
         cResult.add(cNode); 
       } 
     return cResult; 
    } 

    boolean hasType(String csType) { 
     for (IIdentifiable cIdentifiable : get(m_csTYPE).iIdentifiables()) 
      if (csType.equals(cIdentifiable.m_csSubject())) return true; 
     return false; 
    } 

    <T extends CNode> T put(String csPredicate, IObject cObject) { 
     Collection<IObject> cObjects = m_cEdges.get(csPredicate); 
     if (cObjects == null) m_cEdges.put(csPredicate, cObjects = new HashSet<>()); 
     cObjects.add(cObject); 
     return (T) this; 
    } 
} 

class CNamedNode extends CNode implements IIdentifiable { 
    private String m_csSubject; 

    CNamedNode(String csSubject, CLink cType) { 
     super(cType); 
     m_csSubject = csSubject; 
    } 

    public String m_csSubject() { return m_csSubject; } 

    public int hashCode() { 
     return 31 * 1 + ((m_csSubject == null) ? 0 : m_csSubject.hashCode()); 
    } 

    public boolean equals(Object cObject) { 
     if (this == cObject) return true; 
     if (cObject == null) return false; 
     if (getClass() != cObject.getClass()) return false; 
     CNamedNode cOther = (CNamedNode) cObject; 
     if (m_csSubject == null) { 
      if (cOther.m_csSubject != null) return false; 
     } else if (!m_csSubject.equals(cOther.m_csSubject)) return false; 
     return true; 
    } 
} 

import java.util.*; 
class CResult extends HashSet<IObject> { 
    Set<CNamedNode> CNamedNodes() { 
     Set<CNamedNode> cResult = new HashSet<>(); 
     for (IObject cMember : this) 
      if (cMember instanceof CNamedNode) cResult.add((CNamedNode) cMember); 
     return cResult; 
    } 

    Set<CNode> CNodes() { 
     Set<CNode> cResult = new HashSet<>(); 
     for (IObject cMember : this) 
      if (cMember instanceof CNode) cResult.add((CNode) cMember); 
     return cResult; 
    } 

    Set<IIdentifiable> iIdentifiables() { 
     Set<IIdentifiable> cResult = new HashSet<>(); 
     for (IObject cMember : this) 
      if (cMember instanceof IIdentifiable) cResult.add((IIdentifiable) cMember); 
     return cResult; 
    } 

    boolean IsAnyIdentifiable() { 
     boolean bResult = false; 
     for (IObject cMember : this) if (cMember instanceof IIdentifiable) return true; 
     return bResult; 
    } 

    String String() { 
     StringBuilder cResult = new StringBuilder(); 
     boolean bFirst = true; 
     for (String csString : Strings()) { 
      if(bFirst) bFirst = false; else cResult.append(", "); 
      cResult.append(csString); 
     } 
     return cResult.toString(); 
    } 

    Set<String> Strings() { 
     Set<String> cResult = new HashSet<>(); 
     for (IObject cMember : this) 
      if (cMember instanceof CLiteral) cResult.add(((CLiteral) cMember).m_csValue()); 
     return cResult; 
    } 
} 

public static void main(String[] args) { 
    final String m_csNS = "http://animalShelter.example/"; 
    CResult cDogs; 
    CResult cFidos; 
    { 
     CNode cShelter = new CNode(m_csNS + "AnimalShelter"); 
     cShelter.put(
      m_csNS + "hasDog", 
      new CNode(new CLink(m_csNS + "Dog")) 
       .put(m_csNS + "hasName", new CLangString("Fido", "en")) 
       .put(m_csNS + "residence", cShelter) 
     ); 
     cShelter.put(
      m_csNS + "hasDog", 
      new CNamedNode(
       "http://en.wikipedia.org/wiki/Scooby-Doo_(character)", new CLink(m_csNS + "Dog") 
      ) 
       .put(m_csNS + "hasName", new CLangString("Scoobert \"Scooby\" Doo", "en")) 
       .put(m_csNS + "residence", cShelter) 
     ); 

     cDogs = cShelter.get(m_csNS + "hasDog"); 
     cFidos = cShelter.getById(m_csNS + "Dog", m_csNS + "hasName", "Fido"); 
    } 

    if(!cDogs.isEmpty()){ 
     System.out.println("No. of dogs: " + cDogs.size()); 
    } 
    if (cDogs.IsAnyIdentifiable()) { 
     System.out.println("Famous dogs:"); 
     for (CNamedNode cWellKnownDog : cDogs.CNamedNodes()) { 
      System.out.println("- " + cWellKnownDog.get(m_csNS + "hasName").String() + " (" 
        + cWellKnownDog.m_csSubject() + ')'); 
     } 
    } 

    if(!cFidos.isEmpty()){ 
     System.out.println(cFidos.CNodes().size() + " dog(s) called Fido."); 
    } 
} 

これをC++に行うにはどうすればよいですか?私のデータモデルクラス内で、このモデルを使用する関数(この場合はmain())がモデルの内部について気にしない(またはできるだけ少ない)方法でオブジェクト破壊を実装するにはどうすればよいですか?

+0

あなたは 'std :: unique_ptr'と' std :: shared_ptr'について話していますか? http://stackoverflow.com/questions/6876751/differences-between-unique-ptr-and-shared-ptr – Amadeus

答えて

1

コピーを作成することにより、C++ハッシュマップ/セット(std::unordered_mapおよびstd::unordered_set)への挿入が行われます。そしてそれはあなたのデフォルトの選択でなければなりません。 Javaを書いているようにC++を書こうとしないでください。

ディープコピーを避けたい場合は、マップ/セットにオブジェクトへのローポインタを含めることができますが、オブジェクトのライフタイムは別々に管理されます(std::vectorなど)。

しかし、Javaのようなセマンティクスがもっと必要な理由があるかもしれません。おそらく、たとえば、マップ/セットで多態型を所有したいとします。その場合は、おそらくスマートポインタが必要です。一意の所有権を持つことが望ましい(各オブジェクトを所有するスマートポインタは1つだけです)。その場合はstd::unique_ptrを使用するか、共有所有権が必要な場合はstd::shared_ptrを使用することができます。両方の種類のスマートポインタは、std::unordered_mapまたはstd::unordered_setに格納することができ、おおまかに期待するセマンティクスを持つ必要があります。

+0

偉大な答え。それは、私が実際に必要としている[例](https://msdn.microsoft.com/de-de/library/hh279669.aspx#Beispiel)につながった。 – Paramaeleon

+0

@Paramaeleon問題ありません。あなたに警告するために、あなたが望む動作を得るために 'CResult'で返す' std :: unordered_set'にカスタムハッシャーと等価述語を与えなければならないかもしれません –

関連する問題