std::basic_string
-
Hi - ich versuch mich gerade daran, nen eigenen String zu schreiben. Weniger um ihn zu verwenden und vor allem aus langer Weile bzw. um halt ein wenig rumzuprobieren...
Allerdings hab ich eine Frage zum Standard (das hier ist aus dem working draft von 2005, sollte aber auch im aktuellen Standard so sein):21.3.1 basic_string constructors schrieb:
In all basic_string constructors, a copy of the Allocator argument is used for any memory allocation performed by the constructor or member functions during the lifetime of the object.
Der eine Allokator soll also für den kompletten Speicher zuständig sein - das beist sich aber ein wenig mit meinem Ansatz, dass der User das verwendete Array selbst heraussuchen kann.
Dann braucht man fürc_str()
ja bekanntlich noch einen anderen container...
Ist die Lösung damit noch Standard-Konform? Bzw. gibt es eine Möglichkeit, dass der vector den selben(nicht den gleichen^^) allocator nutzt, wie die deque?template< typename TChar, typename traits = std::char_traits<TChar>, typename TAlloc = std::allocator<TChar>, typename array_type = std::deque<TChar, TAlloc> > struct basic_string { struct _m { array_type content; mutable std::vector<value_type, allocator_type> c_str_content; } m; const char* c_str() const { m.c_str_content.reserve(size()+1); m.c_str_content.assign(begin(), end()); m.c_str_content.push_back(value_type()); return &*m.c_str_content.begin(); } };
Dann hab ich noch eine Frage zu
assign()
: Ich habe nirgendwo gefunden, dass bei assign kein zweites Objekt erstellt werden darf und dann einfach geswapt werden darf(also wird das ja mit Sicherheit die bevorzugte Lösung sein - würdet ihr dasreserve(size()+1)
dann trotzdem lassen oder eher weglassen oder einen anderen weg gehen?Danke schon mal,
bb
-
unskilled @logged-off schrieb:
Der eine Allokator soll also für den kompletten Speicher zuständig sein - das beist sich aber ein wenig mit meinem Ansatz, dass der User das verwendete Array selbst heraussuchen kann.
Dann braucht man fürc_str()
ja bekanntlich noch einen anderen container...
Ist die Lösung damit noch Standard-Konform? Bzw. gibt es eine Möglichkeit, dass der vector den selben(nicht den gleichen^^) allocator nutzt, wie die deque?Wahrscheinlich nicht. Wenn du dich gleichzeitig ein wenig am Entwurf des neuen Standards orientierst, wirst du erkennen, das alles andere als ein normales Array für die Speicherverwaltung sowieso eher unerwünscht sein dürfte.
unskilled @logged-off schrieb:
Dann hab ich noch eine Frage zu
assign()
: Ich habe nirgendwo gefunden, dass bei assign kein zweites Objekt erstellt werden darf und dann einfach geswapt werden darf(also wird das ja mit Sicherheit die bevorzugte Lösung sein - würdet ihr dasreserve(size()+1)
dann trotzdem lassen oder eher weglassen oder einen anderen weg gehen?Das sollte zulässig sein, im nächsten Standard sowieso (der bestimmt explizit swap(str) als zulässige Implementation für den move-Fall). Einen Vorteil sehe ich darin nicht (wenn man sowieso kopieren muss): wenn der Speicher des ursprünglichen Strings ausreicht, sollte die Wiederverwendung dieses Speichers effizienter sein. Bedenke, das sowieso nur Typen mit einfacher Kopiersemantik als Zeichentypen zulässig sind, im Gegensatz zum allgemeinen Fall brauchen wir uns hier keine Gedanken um Exceptionsicherheit beim normalen Kopieren machen, denn das kann nicht fehlschlagen.
-
camper schrieb:
Bedenke, das sowieso nur Typen mit einfacher Kopiersemantik als Zeichentypen zulässig sind, im Gegensatz zum allgemeinen Fall brauchen wir uns hier keine Gedanken um Exceptionsicherheit beim normalen Kopieren machen, denn das kann nicht fehlschlagen.
Guter Hinweis, danke
Naja - der einzige richtige Nachteil sind imho die traits-Fkt.
vor allem find() - da weiß ich noch gar nicht, wie ich das mache...bb
-
gut - da bei find() nur im standard steht, dass traits_type::eq und nicht traits_type::find genutzt werden muss, wars doch np...
aber ich hab noch ne Frage zu find_first_of bzw. find:
21.3.6.3 basic_string::find_first_of schrieb:
7.:
size_type find_first_of ( charT c , size_type pos = 0) const { return find_first_of( basic_string<charT,traits,Allocator>(1,c),pos ); }
was ist der Unterschied dieser Fkt und der find-Überladung:
size_type find(charT c , size_type pos = 0) const;
?
Ich konnte keinen finden...
bb
-
Willst du tatsächlich einen
std::string
mit seinen über hundert Memberfunktionen nachbauen? Ich würde mir das nochmals gut überlegen und wenigstens nicht die gleichen Fehler begehen, die schonmal gemacht wurden.Siehe sonst auch http://www.gotw.ca/gotw/084.htm...
unskilled @logged-off schrieb:
was ist der Unterschied dieser Fkt und der find-Überladung:
Ich habe das gefunden:
<a href= schrieb:
http://www.cplusplus.com/reference/string/string/find/">Notice that unlike member find_first_of, whenever more than one character is being searched for, it is not enough that only one of these characters match, but the entire sequence of characters to find must be matched.
BTW: Hast du dein Passwort vergessen und das der E-Mail-Adresse ebenfalls? :p
-
Nexus schrieb:
BTW: Hast du dein Passwort vergessen und das der E-Mail-Adresse ebenfalls? :p
LOL. Ich habe im anderen Thread fast das gleiche gefragt. :p
-
Japp - langeweile
und so, wie ich einen meiner profs kenne, werden wir auch nächstes semester wieder genug Hausarbeiten bekommen, bei denen wir nicht eine einzige Zeile der Standard-Lib nutzen dürfen - also wirds vll nicht mal so sinnlos sein^^ und dümmer wird man dadurch ja nun auch nicht - und (um gleich die ausgeloggt-frage zu beantworten) sitz ich nur am laptop, weil mein (pc-)mainboard kaputt ist und kann hier nich ma ordentlich spielen>.< also hab ich eh nix besseres zu tun.zum 1. link - japp, kannte ich schon - aber wenns so nunmal so standardisiert wurde...
zum 2. link (was du gefunden hattest):
wenn mich nicht alles täuscht, steht dort auch kein unterschied sondern nur, dass es unterschiedliche ergebnisse liefert, sobald nicht nur ein zeichen übergeben wird!?bb
-
— at(xpos+I) == str.at(I) for all elements I of the string controlled by str
...
— at(xpos) == str.at(I) for some element I of the string controlled by str.
Wenn I nur 0 sein kann, weil der entsprechende String nur ein Zeichen hat, kann es offenbar keinen Unterschied geben. Diese Überladungen existieren offensichtlich nur der Vollständigkeit halber beide als degenerierte Versionen des allgemeinen Falls.
-
camper schrieb:
— at(xpos+I) == str.at(I) for all elements I of the string controlled by str
...
— at(xpos) == str.at(I) for some element I of the string controlled by str.
Wenn I nur 0 sein kann, weil der entsprechende String nur ein Zeichen hat, kann es offenbar keinen Unterschied geben. Diese Überladungen existieren offensichtlich nur der Vollständigkeit halber beide als degenerierte Versionen des allgemeinen Falls.
danke
-
Und nochmal... : D
im Gegensatz zu den 100den von find-Fkt, die lediglich
traits_type::eq()
ist die string-compare-fkt so definiert:standard schrieb:
int compare(const basic_string &str) const
{
const size_type rlen = std::min(size(), str.size()); //1 Effects: Determines the effective length rlen of the strings to compare as the smallest of size() and str.size().
return traits_type::compare(data(), str.data(), rlen); //The function then compares the two strings by calling traits::compare(data(), str.data(), rlen).
}standard schrieb:
[traits::compare]
yields: 0 if for each i in [0,n), X::eq(p[i],q[i]) is true; else, a negative value if, for some j in [0,n), X::lt(p[j],q[j]) is true and for each i in [0,j)
X::eq(p[i],q[i]) is true; else a positive value.traits::compare ist also über eq bzw lt definiert.
ist es nun noch standard-konform, wenn man die string-compare-fkt nicht mittels der traits-compare-fkt sondern direkt mit eq implementiert?bb
-
unskilled schrieb:
traits::compare ist also über eq bzw lt definiert.
Das betrifft aber nur die Ermittelung des Rückgabewertes. Eine nutzerdefinierte traits-Klasse könnte durchaus in diesen Funktionen noch anders beobachtbares Verhalten zusätzlich einbauen. Mit anderen Worten: im Standardfall char_traits<char>, char_traits<wchar_t> kannst du machen, was du willst, ansonsten ist es problematisch.
-
camper schrieb:
unskilled schrieb:
traits::compare ist also über eq bzw lt definiert.
Das betrifft aber nur die Ermittelung des Rückgabewertes. Eine nutzerdefinierte traits-Klasse könnte durchaus in diesen Funktionen noch anders beobachtbares Verhalten zusätzlich einbauen. Mit anderen Worten: im Standardfall char_traits<char>, char_traits<wchar_t> kannst du machen, was du willst, ansonsten ist es problematisch.
Das ich das in diesen beiden Fällen machen kann, hab ich auch schon geschlussfolgert.
Schade - ich hatte gehofft, dass du irgend ne Stelle so deutest, dass man einen dem standard entsprechenden traits-typ angeben muss^^Fällt jemandem ein Fall ein, wo es sinnvoll ist, dass jmd. ein compare schreibt, welches nicht dem standard-compare entspricht? Mir ist vorhin keiner eingefallen und jetzt auch noch nicht
bb