Überprüfen Sie, ob gleiche String-Literale an der gleichen Adresse gespeichert sind

8

Ich entwickle eine (C ++) Bibliothek, die ungeordnete Container verwendet. Diese erfordern einen Hasher (normalerweise eine Spezialisierung der Template-Struktur std::hash ) für die Arten der Elemente sie lagern. In meinem Fall sind diese Elemente Klassen, die String-Literale kapseln, ähnlich wie conststr des Beispiels in unten Seite . Die STL bietet eine Spezialisierung für konstante Zeichenzeiger, die jedoch nur Zeiger berechnet, wie hier in den 'Notes' erklärt Abschnitt :

  

Es gibt keine Spezialisierung für C-Strings. %Code%   erzeugt einen Hash des Wertes des Zeigers (der Speicheradresse), es   untersucht nicht den Inhalt eines Zeichenarrays.

Obwohl dies sehr schnell ist (oder so denke ich), ist es vom C ++ - Standard nicht garantiert, ob mehrere gleiche String-Literale an der gleichen Adresse gespeichert sind, wie in diese Frage . Wenn dies nicht der Fall ist, wäre die erste Bedingung von Haschern nicht erfüllt:

  

Für zwei Parameter k1 und k2, die gleich sind, std::hash<const char*>

Ich möchte den Hash unter Verwendung der bereitgestellten Spezialisierung selektiv berechnen, wenn die oben genannte Garantie gegeben wird, oder sonst eines anderen Algorithmus. Obwohl es möglich ist, diejenigen zu fragen, die meine Header enthalten oder meine Bibliothek zum Definieren eines bestimmten Makros erstellen, wäre eine implementierte Implementierung vorzuziehen.

Gibt es irgendein Makro in irgendeiner C ++ - Implementierung, aber hauptsächlich g ++ und clang, deren Definition garantiert, dass mehrere gleiche String-Literale unter der gleichen Adresse gespeichert werden?

Ein Beispiel:

%Vor%     
Kalrish 29.08.2014, 21:14
quelle

2 Antworten

5
  

Gibt es irgendein Makro in irgendeiner C ++ - Implementierung, aber hauptsächlich g ++ und clang, deren Definition garantiert, dass mehrere gleiche String-Literale unter der gleichen Adresse gespeichert werden?

  

Versuch , identische Konstanten (Zeichenfolgenkonstanten und Gleitkommakonstanten) über Kompilierungseinheiten hinweg zusammenzuführen.

     

Diese Option ist der Standard für die optimierte Kompilierung, wenn der Assembler und der Linker dies unterstützen. Verwenden Sie -fno-merge-constants, um dieses Verhalten zu verhindern.

     

Aktiviert bei den Ebenen -O, -O2, -O3, -Os.

  • Visual Studio hat String Pooling ( / GF Option: "Doppelte Strings eliminieren")
  

String-Pooling ermöglicht, dass mehrere Zeiger auf mehrere Puffer als mehrere Zeiger auf einen einzelnen Puffer gedacht sind. Im folgenden Code werden s und t mit derselben Zeichenfolge initialisiert. String-Pooling bewirkt, dass sie auf denselben Speicher verweisen:

%Vor%

Hinweis: Obwohl MSDN char* Zeichenfolgenliterale verwendet, sollte const char* verwendet werden

  • clang hat anscheinend auch die Option -fmerge-constants , aber ich kann nicht viel darüber finden, außer im Abschnitt --help , also bin ich mir nicht sicher, ob es wirklich den gcc entspricht eins:
  

Das Zusammenführen von Konstanten nicht zulassen

Wie auch immer, wie String-Literale gespeichert werden, hängt von der Implementierung ab (viele speichern sie im schreibgeschützten Teil des Programms).

Anstatt Ihre Bibliothek für mögliche implementierungsabhängige Hacks zu erstellen, kann ich nur die Verwendung von std::string anstelle von C-Stil-Strings vorschlagen: Sie verhalten sich genau so, wie Sie es erwarten.

Sie können Ihre std::string direkt in Ihren Containern mit den emplace() Methoden erstellen:

%Vor%     
quantdev 29.08.2014, 21:58
quelle
2

Obwohl C ++ anscheinend keine Möglichkeit bietet, mit String-Literalen zu arbeiten, gibt es eine hässliche, aber etwas praktikable Lösung des Problems, wenn es Ihnen nichts ausmacht, Ihre String-Literale als Zeichenfolgen neu zu schreiben.

%Vor%

Dies ist erforderlich, um Null zurückzugeben. Der Compiler muss sicherstellen, dass, selbst wenn mehrere Übersetzungseinheiten str<'a','b','c'> instanziieren, diese Definitionen zusammengeführt werden und Sie nur mit einem einzelnen Array enden.

Sie müssen jedoch sicherstellen, dass Sie dies nicht mit String-Literalen kombinieren. Jedes String-Literal ist garantiert nicht , um es mit einem der Arrays der Template-Instanziierungen zu vergleichen.

    
hvd 29.08.2014 23:29
quelle

Tags und Links