STL SET und Objekte mit _bstr_t



  • Hallo,

    ich habe bei mir ein sehr seltsames Verhalten und hoffe, dass mir jemand weiterhelfen kann.

    Folgende Struct möchte ich in ein set packen:

    struct
    {
       _bstr_t Vorname;
       _bstr_t Nachname;
    }Name;
    

    Ins set trag ich das dann so ein:

    typedef std::set<Name,less_Name > NAMESET;
    NAMESET myNameset;
    std::pair<NAMESET::iterator, bool> myIterator;
    Name myName;
    myName.Vorname = _T("Hans");
    myName.Nachname = _T(Dampf");
    myIterator = myNameset.insert(myName);
    

    ...natürlich trag ich einige mehr ein.
    Wenn ich jetzt durch das set iteriere, ist alles noch ok.

    Um jetzt schnell einen Eintrag zu finden, muss noch "less_Name" definiert werden um ein Sortierkriterium zu bestimmen.

    class less_Name
    {
        bool operator()(const Name n1, const Name n2)
        {  return true wenn n1 < n2 ist }
    }
    

    Jetzt kann ich versuchen einen Namen zu finden:

    Name findName;
    findName.Vorname = _T("Otto");
    findName.Nachname = _T("Meier");
    NAMESET::iterator myIterator;
    myIterator = myNameset.find(findName);
    

    So, und jetzt kommts zu meinen Problem. Der Eintrag, der existieren müsste wird nicht gefunden (nicht immer).
    Das Problem ist nicht richtig reproduzierbar (er findet manchmal, manchmal nicht).
    Ich vermute schwer, dass es mit den _bstr_t´s zusammenhängt.
    Der m_RefCount des _bstr_t´s ist eins niedriger als bei den anderen Einträgen. Der Debugger zeigt als Inhalt nur ?????????? obwohl m_str noch korreckt "Otto" ist.

    Vielen Dank für jeden Tipp!



  • _bstr_t
    = _T("Hans"); ???

    nur als frage, wieso als TCHAR literal ... _bstr_t ist multibyte, also nen wchar. passender waere = L"Hans";
    Haette dein Programm auch weniger zu rechnen mit ...

    Als was brauchst du die Namen eigentlich, wirklich als BSTRs ??? vielleicht kaemst prinzipiell mit nem std::basic_string<TCHAR> besser ... ? (das _T() kommt ja ned von ungefaehr ? )

    am rande, aber das hasst sicher auch ned so gemeint ...

    Um jetzt schnell einen Eintrag zu finden, muss noch "less_Name" definiert werden um ein Sortierkriterium zu bestimmen.

    🙂 Du brauchst den operator ned um finden zu koennen, sondern um ueberhaupt einfuegen zu koennen, nen set fuehrt eine liste sortiert ! 🙂

    wieso machst du es dir beim einfuegen so schwer ? weiterhin wuerd ich die name geschichte als klasse machen und der nen CCtor, nen Ctor mit den Werten und nen < Operator spendieren ... machts etwas uebersichtlicher.

    einfugen kannst dann so

    typedef std::set<Name> set_t;
    
    set_t mytest;
    
    Name  myName(L"Hans",L"Dampf");
    
    set_t::iterator it = mytest.insert(myName);
    

    und suchen kannst dann mit

    Name  myName(L"Hans",L"Dampf");
    
    set_t::iterator it = mytest.find(myName); 
    if(it != mytest.end())
    {
        //gefunden
    }
    

    Ciao ...



  • Danke!

    Hilft mir aber leider noch nicht weiter.
    Die BSTR`s brauch ich, weil das set über eine COM Funktion gefüllt wird.

    STDMETHODIMP CName::getNamen(BSTR Vorname, BSTR Nachname)
    {
       _bstr_t bstVorname(Vorname, true);
       _bstr_t bstNachname(Nachname, true);
       Name myName(bstVorname, bstNachname);
    
       NAME_SET::iterator it = myNameset.find(myName);
    }
    

    ...tja, und irgendwas verschiesst jetzt meinen b_str_t (komischerweise nur den Vornamen, der Nachname war bis jetzt immer ok)
    😕

    nur als frage, wieso als TCHAR literal ... _bstr_t ist multibyte, also nen wchar. passender waere = L"Hans";
    Haette dein Programm auch weniger zu rechnen mit ...

    da kann ich nur sagen, ich bin mit Strings in C auf Kriegsfuss. Ich nehm was funktioniert und frag nicht lange nach. Aber im ernst, ich müsste mich genau mit dem Thema noch mal ein paar Tage beschäftigen!!



  • wie gibst du dein ergebniss zurueck ?
    Ich mein suchen und nur die information ob es das gibt ? vielleicht liegt da der haken ???

    Oder hast du in der funktion debuggt ?

    Auf was steht der iterator nach dem find, hoffentlich nicht auf end !!!

    Du arbeitest mit der ATL ??? Dann nimm mal lieber CComBSTR fuer deine Strings ...

    STDMETHODIMP CName::getNamen(BSTR Vorname, BSTR Nachname)
    {
        HRESULT hr = S_FALSE;
       _bstr_t bstVorname(Vorname, true);
       _bstr_t bstNachname(Nachname, true);
       Name myName(bstVorname, bstNachname);
    
       NAME_SET::iterator it = myNameset.find(myName);
        if(it != myNameset.end())
        {
            hr = S_OK;
        }
        return hr ;
    }
    

    schau mal, ob er in das if springt ....

    Ciao ...



  • jetzt hab ich den entscheidenden Tip gekriegt. juhu!!

    Ich muss mich glaube ich bei dir entschuldigen, weil das was bei mir zum Problem führte hab ich nicht beschrieben 😞

    BSTR bsVorname,bsNachname;
        get_Vorname(&bsVorname);
        _bstr_t bstVorname(bsVorname, false); //erzeugt Referenz auf bsVorname
        ....tue irgendwas
        _bstr_t bstVorname_fuer_set = bstVorname; //erzeugt weitere Referenz auf bsVorname
        ::SysFreeString(bsVorname);
        NAMESET::iterator it = myNameSet.insert(bstVorname_fuer_set);
    

    Jetzt hab ich natürlich wieder einiges weggelassen/vereinfacht, aber mein Fehler wird hier klar:

    _bstr_t bstVorname_fuer_set = bstVorname; //erzeugt weitere Referenz auf bsVorname
    

    Ich habe damit gerechnet, dass eine neue Instanz angelegt wird, wird aber nicht. Somit war ich dem Zufall ausgeliefert, ob der BSTR noch gültig war an der Stelle oder nicht.
    Wenigstens hab ich was gelernt:

    _bstr_t = BSTR; //legt neue Instanz an
    _bstr_t = _bstr_t; //legt nur ne Referenz an
    

    Komisch ist nur, dass es das SET nicht schon beim Eintragen verschossen hat. Erst beim find kamen die Probleme ans Tageslicht.

    Und vielen dank für deine Antworten. cu


Anmelden zum Antworten