[C++] Waarom geen string ref class?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
In C++ mis ik een 'string ref' class, een const char* pair dat wijst naar een string. STL gebruikt wel iterator pairs als input types, maar functies die strings als input parameters hebben, willen een reference naar std::string.
Op die manier ben je verplicht een std::string te construeren, terwijl dit helemaal niet nodig is.
Weet iemand waarom dit is?
Zelfs Boost heeft zo'n class niet voor zover ik weet.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Volgens mij zijn er in de standaard library geen functies die een std::string als parameter verwachten (anders dan de classes die rond std::string werken natuurlijk, zoals std::string zelf en std::stringstream). std::exception vraagt bijvoorbeeld gewoon om een const char *.

Maar verder ben ik het met je eens. Ik had wel graag een immutable versie van een string verwacht die je gewoon een const char* kon voeren, die de boel dan niet gaat kopiëren.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Andre-85
  • Registratie: April 2003
  • Niet online

Andre-85

Sid

Volgens de standaard verwacht std::exception helemaal niets ;) Ik neem aan dat je werkt met Visual Studio? Daarin is std::exception uitgebreid met een constructor die een const char* verwacht. std::runtime_error heeft een constructor met een const std::string& als parameter.

Lorem
Whenever we feel the need to comment something, we write a method instead. - Martin Fowler
People who think they know everything really annoy those of us who know we don't - Bjarne Stroustrup


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ah ja, ik was idd de war met de derived classes, en liep daarbij op de standaard vooruit (C++0x heeft wel const char * ctors voor die classes). Maar je hebt gelijk dat die idd ook std::string ondersteunen.

[ Voor 6% gewijzigd door .oisyn op 07-06-2010 14:17 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

het voordeel van std::string (&) als argument gebruiken is dat ownership een stuk simpeler ligt:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct foo
{
  const char *_s;
  foo(const char *s) : _s(s) {}
  ~foo() { free(_s); } //1
  ~foo() { delete [] _s; } //2
  ~foo() { delete _s; } //3
  ~foo() { } //4
};

void main()
{
  foo a("foo"); //mag alleen met 4
  foo b(strcpy("foo")); //mag alleen met 1
}

//dit is altijd duidelijk:
struct bar
{
  std::string _s;
  bar(const std::string &s) : _s(s) {}
  ~bar() {} //ook weglaatbaar
};


C++ hoeft niet delete, delete[] en free allemaal naar elkaar te mappen (wat VisualC++ wel doet)

-niks-


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
.oisyn schreef op maandag 07 juni 2010 @ 11:18:
Volgens mij zijn er in de standaard library geen functies die een std::string als parameter verwachten (anders dan de classes die rond std::string werken natuurlijk, zoals std::string zelf en std::stringstream). std::exception vraagt bijvoorbeeld gewoon om een const char *.
Is dat in c++0x niet gefixed? Of werkt ofstream(string&) nog steeds niet?
Maar verder ben ik het met je eens. Ik had wel graag een immutable versie van een string verwacht die je gewoon een const char* kon voeren, die de boel dan niet gaat kopiëren.
Tijd voor een nieuwe Boost lib.
MLM schreef op maandag 07 juni 2010 @ 14:59:
het voordeel van std::string (&) als argument gebruiken is dat ownership een stuk simpeler ligt:
Ownership is heel simpel: geen.

[ Voor 14% gewijzigd door Olaf van der Spek op 07-06-2010 15:18 ]


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Olaf van der Spek schreef op maandag 07 juni 2010 @ 15:17:
[...]

Is dat in c++0x niet gefixed? Of werkt ofstream(string&) nog steeds niet?

[...]

Tijd voor een nieuwe Boost lib.

[...]

Ownership is heel simpel: geen.
Ja dat kan, maar dan gaan objecten alsnog kopietjes maken als ze buiten de directe call die string nog nodig hebben (en waarschijnlijk in een object member opslaan), omdat ze geen ownership hebben. Dan kan je net zo goed een std::string gebruiken.

En als de functie de string enkel in de directe functie nodig heeft, kan de functie gewoon een std::string & als argument hebben en c_str() gebruiken, en word er ook geen kopie gemaakt. Dan blijft het enige geval van overhead als je nog geen std::string instance hebt (dan moet je dus een std::string construeren).

Maar je zou het waarschijnlijk kunnen hacken door een struct te maken met dezelfde members als je std::string implementatie en een operator const std::string & eraan te hangen (maar dat is wel tricky, je bent afhankelijk van je specifieke std::string implementatie, en gaat ervan uit dat alle const members die aangeroepen worden vanuit de functie die const std::string & als argument neemt van std::string niets veranderen (dus geen mutables members)).

Waarschijnlijk is het makkelijker om gewoon overal std::string te gebruiken, dan hoef je geen tijdelijke std::string's te construeren ;)

[ Voor 2% gewijzigd door MLM op 07-06-2010 16:21 . Reden: hacks :( ]

-niks-


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

MLM schreef op maandag 07 juni 2010 @ 14:59:
het voordeel van std::string (&) als argument gebruiken is dat ownership een stuk simpeler ligt:
Het idee van Olaf's feature is dat de class waar je de pointer aan geeft sowieso geen ownership krijgt. Hij is dus ook niet verantwoordelijk voor het opruimen ervan. Het is de verantwoordelijkheid van de caller dat de char buffer blijft bestaan zolang het object wat je geconstruct hebt met die buffer bestaat.
MLM schreef op maandag 07 juni 2010 @ 16:18:
Dan blijft het enige geval van overhead als je nog geen std::string instance hebt (dan moet je dus een std::string construeren).
Dat was nou juist het hele punt :)

[ Voor 21% gewijzigd door .oisyn op 07-06-2010 17:12 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Maar over welke functie(s) hebben we het nu? Sowieso is een paar const char*s naturlijk ook een paar iterators, dus string functies met een iterator equivalent tellen niet.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
MSalters schreef op dinsdag 08 juni 2010 @ 18:46:
Maar over welke functie(s) hebben we het nu? Sowieso is een paar const char*s naturlijk ook een paar iterators, dus string functies met een iterator equivalent tellen niet.
Het gaat niet zozeer om standaard C++ (STL) functies, maar om alle functies in apps / libs die een const string& als parameter hebben.

Iets algemener kun je de class ook met een unsigned char* gebruiken en dan gaat het over alle functies die een pointer (void*, (unsigned) char*) en size als parameter hebben. Bijvoorbeeld (wrappers van) recv en send.

Range (iterator pair) parameters werken trouwens veel beter dan twee losse iterator parameters.

[ Voor 8% gewijzigd door Olaf van der Spek op 08-06-2010 21:52 ]


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Er komt een oplossing (in C++17?): http://en.cppreference.co...imental/basic_string_view
Toch fijn :p

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nice :).

Ik heb een vergelijkbare klasse in mijn codebase. Maar ik heb de keuze gemaakt om wél c_str() te supporten en géén substr(). Ik gebruik het ook voornamelijk om functies goedkoop een string te laten accepteren, of je input nou een char* of een std::string is.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Heb je c_str() zo vaak nodig?

Soortgelijke klassen gebruik ik ook voor read() en write() functie parameters en in veel andere situaties.
Je kunt natuurlijk ook twee klassen hebben, een zonder c_str() en een met c_str().

[ Voor 77% gewijzigd door Olaf van der Spek op 26-03-2015 21:21 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ja, alle OS calls verwachten null terminated strings :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
't Probleem is dat by design een ref class geen kopie maakt, terwijl een substring null-terminaten eigenlijk een kopie vereist. Of je moet hele vieze dingen doen met een temporary die gedurende z'n levensduur de onderliggende string edit.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 16:28
Een ref class hoeft natuurlijk geen substring-operatie te ondersteunen; dat is een afweging die je maakt, zoals .oisyn al eerder noemde.

Op mijn werk gebruiken we trouwens ook een klasse met de semantics van std::basic_string_view, dus zonder c_string, maar met substring-operatie. Het voordeel daarvan is dat je makkelijk suffixes/prefixes kunt strippen, tokenizen, et cetera. Dat is wat mij betreft de reden dat die semantics te prefereren zijn.

Acties:
  • 0 Henk 'm!

  • ThomasG
  • Registratie: Juni 2006
  • Laatst online: 15:52
Wat je zoekt is string interning. Dat zit (helaas) niet standaard in C++, maar je kunt een vergelijkbaar effect creëren met bijvoorbeeld boost::flyweight<std::string> of een alternatieve string library te gebruiken.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, dat zoekt hij helemaal niet :). Het boeit niet dat er meerdere kopies van dezelfde string bestaan. Waar het om gaat is dat een kopie van het object niet ook een kopie van de string zelf impliceert.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
MSalters schreef op maandag 30 maart 2015 @ 11:42:
't Probleem is dat by design een ref class geen kopie maakt, terwijl een substring null-terminaten eigenlijk een kopie vereist. Of je moet hele vieze dingen doen met een temporary die gedurende z'n levensduur de onderliggende string edit.
Als je zowel string_view als zstring_view hebt kan zstring_view::substr() een string_view returnen.
.oisyn schreef op maandag 30 maart 2015 @ 10:58:
[...]

Ja, alle OS calls verwachten null terminated strings :)
Yep, wanneer zou dat gefixed worden? :p
Ik weet niet wat voor apps je ontwikkelt maar vaak worden lang niet alle strings gebruikt voor OS calls.

[ Voor 26% gewijzigd door Olaf van der Spek op 31-03-2015 14:50 ]

Pagina: 1