2013-08-26 10 views
8

Podczas szumiące nad projektem C++ 14/C++ 1r (n3690) zauważyłem, aby wprowadzenie basic_string litertal przyrostków w sekcji §21.7:Czy łańcuchy literowe basic_string są szybsze czy obsługiwane szybciej podczas kompilacji?

inline namespace literals { 
inline namespace string_literals { 
    // 21.7, suffix for basic_string literals: 
    string operator "" s(const char *str, size_t len); 
    u16string operator "" s(const char16_t *str, size_t len); 
    u32string operator "" s(const char32_t *str, size_t len); 
    wstring operator "" s(const wchar_t *str, size_t len); 
} 
} 

moje pytania są:

  • Czy istnieje możliwość bycia szybszym w czasie wykonywania z literami basic_string?
  • Czy moja "naiwna" implementacja jest całkowicie błędna?
  • Czy układ danych w pamięci ROM może się różnić od literatury basic_string lub jakąkolwiek inną różnicę podczas kompilacji w czasie pracy?

Tło

wiem, że ta pozwala na bezpośrednie wykorzystanie napisowych takiego:

std::string s1 = "A fabulous string"s; 

void sfunc(std::string arg); 

int main() { 
    sfunc("argument"s); 
} 

Ale to, co jest zaletą, że w ciągu opierając się na konstruktora konwersjistring(const char*)?

„Stara” kod będzie wyglądał:

std::string s1 = "A fabulous string"; // c'tor string(const char*) 

void sfunc(std::string arg); 

int main() { 
    sfunc("argument"); // auto-conversion via same c'tor 
} 

O ile widzę realizacja operator "" s() byłoby w zasadzie wyglądać następująco:

std::string operator "" s(const char* lit, size_t sz) { 
    return std::string(lit, sz); 
} 

Tak, tylko użycie ten sam c'tor. I przypuszczam, że to musi być zrobione w czasie wykonywania, czy jestem w błędzie?

Edit: W Nicol Bolas wskazał poprawnie poniżej mój przykład nie nie używać tego samego konstruktora, ale jeden z dodatkowej długości - co jest bardzo przydatne do budowy, oczywiście. Pozostaje mi pytanie: czy lepiej dla kompilatora umieszczać literały łańcuchowe w ROM, czy coś podobnego podczas kompilacji?

Odpowiedz

6
  • Czy istnieje możliwość, aby być szybciej w czasie wykonywania z literałów basic_string?

Jak już wspomniano, długość ciągu jest znana i automatycznie przekazywana do konstruktora.

  • Czy mój "naiwny" realizacja całkowicie błędne?

Nie, zgadza się.

  • Czy układ danych w pamięci ROM być inna z basic_string literały, lub jakiekolwiek inne różnice w czasie kompilacji kontra run-time?

Prawdopodobnie nie, ponieważ istotne basic_string konstruktor nie jest constexpr więc nie będzie kwalifikował się do inicjalizacji statycznej, więc prawdopodobnie nie można umieścić w pamięci ROM i musi być zrobione w czasie wykonywania.

4

Po prostu użycie tego samego c'tor.

OK, zobaczmy, jak to będzie wyglądać:

string fromLit = "A fabulous string"s; 
string fromBare = string("A fabulous string"); 

Zobacz czegoś brakuje w fromBare? Pozwól mi zaklęcie to dla ciebie:

string fromBare = string("A fabulous string"/*, NOTHING*/); 

Tak, nie można uzyskać długość napisu bez ... coraz to jest długość. Co oznacza, że ​​fromBare będzie musiał powtórzyć literał, aby znaleźć znak \0. W czasie wykonywania. fromLit nie będzie; kompilator podaje długość ciągu jako parametr określony w czasie kompilacji. Każdy kompilator, którego warto użyć, po prostu upieje długość kodu wykonywalnego.

I nawet jeśli to nie było, sprawa jest jeszcze lepsza z innych powodów. Rozważ to:

void SomeFunc(const std::string &); 
void SomeFunc(const char *); 

SomeFunc("Literal"); 
SomeFunc("Literal"s); 
SomeFunc(std::string("Literal")); 

Dwa ostatnie to samo (minus punkt zrobiłem wcześniej), ale jeden z nich jest znacznie krótszy. Nawet jeśli zatrudniasz using std::string (lub głupio using namespace std;), drugi jest jeszcze krótszy. Jednak dokładnie wiadomo, co się dzieje.

+0

Bardzo dobry punkt! Posiadanie długości jest zaletą, z pewnością. – towi

+0

Co do wydajności, wątpię, aby literały łańcuchowe dały impuls do używania statycznego const: 'static std :: string lit (" Literal ");'; mogą nawet znacznie wolniej. Konieczność wymyślenia nazwy i zadeklarowania dodatkowej zmiennej jest jednak trudna, a literały łańcuchowe są zdecydowanie poprawą z tych powodów. –

1

Zapewnia większe bezpieczeństwo podczas kompilacji.

Rozważmy How do you construct a std::string with an embedded null?

Jedynym sposobem, aby skonstruować std::string z ciągu dosłownym, który zawiera znak null jest albo określić rozmiar napisu dosłowny (podatne na błędy), użyj initializer_list składni (gadatliwy) lub zrobić jakiś rodzaj pętli z wieloma połączeniami do push_back (jeszcze bardziej gadatliwy). Jednak w przypadku konstruktora dosłownego rozmiar jest automatycznie przekazywany, usuwając możliwe źródło błędu.

+0

Interesujący punkt, ale dość rzadki. Literały ciągu zawierające '\ 0' - zdarzają się, ale rzadko. A ponieważ autor ma kontrolę nad literałami ciągów, wprowadza tylko mały problem. +1 nonethesese, za interesujący aspekt. – towi

Powiązane problemy