template funktion
-
der Effekt ist ähnlich wie strdup
http://msdn.microsoft.com/en-us/library/y471khhc%28v=vs.80%29.aspx
wobei strdup einen nullterminierten String annimmt und einen nullterminierten String zurückgibt
deine Funktion nimmt einen nullterminierten String an und gibt KEINEN nullterminierten String zurück
-
Aber ich könnte den String doch vor dem zurückgeben null-terminieren, oder?
-
dann muß du str.length()+1 nehmen, weil std::string nicht nullterminiert ist und str.length() die Länge ohne Nullzeichen zurückgibt
-
pumuckl schrieb:
Soahc schrieb:
Die letzte Variante funktioniert bei mir leider nicht. Ich kann zwar kompilieren, aber die Elemente werden nicht getauscht.
Mal mit dem Debugger reingeschaut?
/edit: ich kanns nachstellen, dass das nicht funktioniert: http://ideone.com/kOLmiU
Du hast die abschließende Null im Suchstring. Mach aus
lit + Neinlit + N - 1und es funktioniert.
-
unique_ptr: http://www.cplusplus.com/reference/memory/unique_ptr/?kw=unique_ptr
Vereinfacht gesagt, ist das ein Zeiger, dessen Inhalt automatisch gelöscht wird.
Dadurch können gar keine Speicherleaks mehr entstehen.
-
unique_ptr geht nur bedingt als return value ...
hier ist zur Abwechslung mal eine Variante mit strdup#include <iostream> #include <string> #include <string.h> char * MyStrDup(const char * p) { return _strdup(p); } wchar_t * MyStrDup(const wchar_t * p) { return _wcsdup(p); } template <typename char_t> const char_t * doSomeThing(const char_t * p) { std::basic_string<char_t> tmp(p); // do something with tmp return MyStrDup(tmp.c_str()); } int main() { const char * p1 = "abc"; const wchar_t * p2 = L"def"; const char * p3 = doSomeThing(p1); const wchar_t * p4 = doSomeThing(p2); std::cout << p3 << std::endl; std::wcout << p4 << std::endl; free((void *)p3); free((void *)p4); }
-
hier ist zur Abwechslung mal eine Variante mit unique_ptr
#include <iostream> #include <string> #include <memory> #include <string.h> char * MyStrDup(const char * p) { size_t uLen = strlen(p) + 1; char * pNew = new char [uLen]; memcpy(pNew, p, uLen); return pNew; } wchar_t * MyStrDup(const wchar_t * p) { size_t uLen = wcslen(p) + 1; wchar_t * pNew = new wchar_t [uLen]; wmemcpy(pNew, p, uLen); return pNew; } template <typename char_t> char_t * doSomeThing(const char_t * p) { std::basic_string<char_t> tmp(p); // do something with tmp return MyStrDup(tmp.c_str()); } int main() { const char * p1 = "abc"; const wchar_t * p2 = L"def"; std::unique_ptr<char[]> p3(doSomeThing(p1)); std::unique_ptr<wchar_t[]> p4(doSomeThing(p2)); std::cout << p3.get() << std::endl; std::wcout << p4.get() << std::endl; }
-
dd++ schrieb:
unique_ptr geht nur bedingt als return value ...
Inwiefern?
-
in diesem speziellen Fall möchte der Auftraggeber wohl einen char * als return value
... und was der Auftraggeber will, das bekommt er auch ...im allg. kann man den unique_ptr nicht kopieren, man muß dazu noch ein std::move bemühen
... es sei denn, der Compiler unterstützt copy elision und es ist in diesem Fall anwendbar und es ist nicht durch irgend eine Compileroption deaktiviert ...
-
dd++ schrieb:
im allg. kann man den unique_ptr nicht kopieren
Man kann den unique_ptr unter keinen Umständen kopieren
dd++ schrieb:
man muß dazu noch ein std::move bemühen
Oder er ist schon eine RValue
dd++ schrieb:
... es sei denn, der Compiler unterstützt copy elision und es ist in diesem Fall anwendbar und es ist nicht durch irgend eine Compileroption deaktiviert ...
Das darf der Compiler nur verwenden, wenn es einen Kopierkonstruktor gibt. Optimierungen verändern doch nicht die Semantik.
-
zur weitergehenden Lektüre gucke hier:
http://stackoverflow.com/questions/4316727/returning-unique-ptr-from-functions
-
dd++ schrieb:
zur weitergehenden Lektüre gucke hier:
http://stackoverflow.com/questions/4316727/returning-unique-ptr-from-functions
Was willst du damit sagen? Statt Semantik hätte ich vielleicht Kompilierbarkeit sagen sollen, aber dein Post ist damit immer noch kreuzfalsch.
-
pumuckl schrieb:
Oder beide Varianten von Werner zusammen, um unnötige Temporaries zu vermeiden (C++11 move-Ctors). Für die Literale muss man dann noch einen kleinen Umweg gehen:
std::pair<char const*, char const*> getReplacement(char*) { return std::make_pair("Element", "Tnemele"); } std::pair<wchar_t const*, wchar_t const*> getReplacement(wchar_t*) { return std::make_pair(L"Element", L"Tnemele"); } template< typename E, typename Traits > std::basic_string< E, Traits > replaceElements( std::basic_string< E, Traits > str ) { typedef std::basic_string< E, Traits > string_t; auto replacement = getReplacement((E*)0); string_t tag(replacement.first); auto pos = str.find(tag); if (pos != string_t::npos) str.replace(pos, tag.length(), replacement.second); return str; } template <typename E> auto replaceElements(E const* ptr) -> std::basic_string<E> { return replaceElements(std::basic_string<E>(ptr)); }Wozu dieser dummy parameter in
getReplacement? So geht ist es besser:std::pair<char const*, char const*> getReplacement() { return std::make_pair("Element", "Tnemele"); } std::pair<wchar_t const*, wchar_t const*> getReplacement() { return std::make_pair(L"Element", L"Tnemele"); } ... getReplacement<E>();