2016-10-06 4 views
21

Ich habe eine einfache Frage. Ich möchte wissen, ob std::string Speicher jedes Mal in C++ zuweist. mit dem Konstruktor const char*Benötigt ein std :: string immer Heapspeicher?

char* first_string = new char[5]; 
strcpy(first_string, "test"); 
std::string tst_first_string(first_string); 
std::string tst_second_string("test"); 
+6

*** wenn std :: string Alloc jedes Mal in C++ *** Ich glaube, es ist die Implementierung definiert und mit den meisten Implementierungen ist die Antwort nein. – drescherjm

+0

http://stackoverflow.com/questions/21694302/what-are-the-mechanics-of-short-string-optimization-in-libc – tkausl

Antwort

20

Beide tst_first_string und tst_second_string gebaut werden:

In meinem Code, so scheint es, dass der Konstruktor mehr Speicherplatz wird tst_first_string als für tst_second_string zu konstruieren. Da die Anzahl der Zeichen vor der Nul-Terminator in beiden Fällen gleich ist, würden Sie vorstellen, dass die Konstruktion genau identisch sein wird. Das heißt, der C++ - Standard ist absichtlich vage, was in Bezug auf die Speicherverwaltung passieren muss, so dass Sie nicht mit absoluter Sicherheit wissen werden.

Beachten Sie auch, dass viele std::string Implementierungen nutzen, um eine kurze Zeichenfolge Optimierung Technik für kleine Strings, die das gesamte Objekt verursacht mit automatischer Speicherdauer in den Speicher geschrieben werden. In Ihrem Fall wird dynamischer Speicher möglicherweise überhaupt nicht verwendet.

Was wir wissen, für sicher ist, dass von C++ 11 ab, kopieren Sie auf Schreib Semantik für std::string ist nicht mehr zulässig, so zwei verschiedene Strings wird erstellt werden.

+3

Es hängt auch vom Zuordner ab. Man kann einen stack-basierten Allocator verwenden, in diesem Fall ist kein Heap involviert, egal was passiert. – vsoftco

+1

@vsoftco Es ist nicht mehr "std :: string", wenn Sie den Zuordner ändern. –

+0

@ T.C. Oh ja, du hast recht, es ist 'std :: basic_string' ... – vsoftco

11

Es hängt von der Implementierung und der Länge der Zeichenfolge ab.

Die meisten großen Implementierungen haben kurze Zeichenfolge Optimierung (SSO), wo die Zeichenfolge im String-Objekt selbst gespeichert wird.

-3

Zeichenfolgenliterale sind schreibgeschützt. Eine wahrscheinliche Optimierung besteht also darin, dass wenn ein std :: string auf ein Literal zeigt, er nur aus einem char * plus einem Flag besteht, um zu sagen, dass es das ist, was es darstellt. Wenn Sie darauf schreiben, muss es natürlich Speicher reservieren.

+0

Während ich glaube, dass eine solche Optimierung technisch legal ist (Sie können kein gültiges C++ - Programm schreiben, das erkennen lässt, ob es vorhanden ist oder nicht), bin ich mir ziemlich sicher, dass kein Compiler/Bibliothek (und beide müssen kooperieren) solche implementieren eine Optimierung. –

+0

Sie müssten zusammenarbeiten, aber nicht tief. Zeichenfolgenliterale befinden sich in einem anderen Speicherbereich als Stapel-, Heap- oder (normalerweise) beschreibbare globale Elemente. Nicht dass ich jemals eine std :: string implementiert hätte. Es könnte ein Problem mit der Throw-Semantik geben (Ist str [0] = 'x' kein Wurf?). –

+0

@MalcolmMcLean: Copy-on-Write ist für 'std :: string' nicht erlaubt, so dass Sie nicht nur auf ein String-Literal zeigen und verfolgen können, wenn es kopiert werden muss. – GManNickG

1

Dies ist implementierungsdefiniert, aber als Beispiel verwendet die Implementierung std::basic_string in Visual C++ 2015 Update 3 ein internes Array, wenn die Länge der Zeichenfolge weniger als 16 Byte beträgt. Hier ist eine stark bearbeitete Teil _String_val von :

template<class _Val_types> 
class _String_val 
{ 
public: 
    typedef typename _Val_types::value_type value_type; 

    enum 
    { // length of internal buffer, [1, 16] 
     _BUF_SIZE = 16/sizeof (value_type) < 1 ? 1 
      : 16/sizeof (value_type) 
    }; 

    value_type *_Myptr() 
    { // determine current pointer to buffer for mutable string 
     return (this->_BUF_SIZE <= _Myres 
      ? _Bx._Ptr 
      : _Bx._Buf); 
    } 

    union _Bxty 
    { // storage for small buffer or pointer to larger one 
     value_type _Buf[_BUF_SIZE]; 
     pointer _Ptr; 
    } _Bx; 
}; 

Wenn Sie bei _Myptr() anschauen, werden Sie feststellen, _Buf verwendet wird, wenn die Länge kleiner als _BUF_SIZE und _Ptr sonst verwendet wird.

Es ist unnötig zu sagen, dass Sie sich nicht darauf verlassen sollten, dass dies für etwas anderes als diese spezielle Implementierung der Standardbibliothek gilt. Es ist ein internes Detail, das sich jederzeit ändern kann.

Verwandte Themen