2011-11-09 14 views
20

Sto imparando C++ dall'inizio e non riesco a ottenere l'argomento di tutte le stringhe.Dichiarazione stringa C++

Qual è la differenza tra i seguenti tre codici?

  1. std::string s = std::string("foo");
  2. std::string s = new std::string("foo");
  3. std::string s = "foo";
+0

Nota che in genere si desidera utilizzare l'opzione 4: 'std :: string s (" foo ");' –

+0

@JerryCoffin: come è diverso dall'opzione 3? –

+2

@MikeSeymour: esegue l'inizializzazione diretta anziché l'inizializzazione della copia. Almeno concettualmente, # 3 crea una stringa temporanea inizializzata dalla costante fornita, quindi usa il costruttore di copie per creare 's' da quel valore (sebbene, ammettiamolo, il compilatore di solito lo ometterà e farà l'equivalente dell'inizializzazione diretta). –

risposta

32
std::string s = std::string("foo"); 

Questo crea un oggetto temporaneo std::string contenente "pippo", quindi assegna a s. (Si noti che i compilatori possono elidere la temporanea. L'elison temporanea in questo caso è esplicitamente consentito dalla norma C++.)

std::string s = new std::string("foo"); 

Si tratta di un errore di compilazione. L'espressione new std::string("foo")crea un std::string nel negozio gratuito e restituisce un puntatore a std::string. Quindi tenta di assegnare il puntatore restituito di tipo std::string* a s di tipo std::string. Il design della classe std::string impedisce che ciò accada, quindi la compilazione fallisce.

C++ non è Java. Questo non è il modo in cui gli oggetti vengono in genere creati, perché se si dimentica dil'oggetto std::string restituito si perde memoria. Uno dei principali vantaggi dell'utilizzo di std::string consiste nel fatto che gestisce automaticamente il buffer di stringa sottostante, quindi new -in questo tipo di sconfitte.

std::string s = "foo"; 

Questo è essenzialmente lo stesso come # 1. Inizializza tecnicamente una nuova stringa temporanea che conterrà "pippo", quindi la assegna a s. Di nuovo, i compilatori in genere elideranno il temporaneo (e in effetti praticamente tutti i compilatori non stupidi oggigiorno di fatto eliminano il temporaneo), quindi in pratica costruisce semplicemente un nuovo oggetto chiamato s sul posto.

In particolare richiama un costruttore di conversioni in std::string che accetta un argomento const char*. Nel codice precedente, il costruttore di conversione deve essere non-explicit, altrimenti si tratta di un errore del compilatore. Il costruttore di conversione è in realtà non- explicit per std::string s, quindi quanto sopra viene compilato.

In questo modo vengono in genere inizializzati gli std::string s. Quando lo s esce dal campo di applicazione, l'oggetto s verrà distrutto insieme al buffer di stringa sottostante. Si noti che quanto segue ha lo stesso effetto (ed è un altro modo tipico in cui vengono inizializzati i valori std::string), nel senso che produce anche un oggetto chiamato s contenente "pippo".

std::string s("foo"); 

Tuttavia, there's a subtle difference between std::string s = "foo"; and std::string s("foo");, uno dei quali è che il costruttore di conversione può essere explicit o non explicit nel caso precedente.

+2

+1 per essere la risposta che menziona i compilatori non necessariamente creando un temporaneo in # 1. –

+1

Nota che il numero 1 e il numero 3 sono equivalenti per quanto riguarda la lingua. – avakar

+0

Quindi 'std :: string (" foo ")' crea "pippo" nello stack e 'new std :: string (" pippo ")' crea foo sull'heap? –

2
  1. Crea un oggetto temporaneo di stringa e copia il valore di s
  2. Non compilare, new std::string("foo") restituisce un puntatore a qualche memoria appena allocata. Affinché funzioni, è necessario dichiarare s come puntatore a una stringa std::string* s.
  3. Costruisce una stringa da una stringa C.

È necessario utilizzare la terza opzione nella maggior parte dei casi, se non tutti.

2

1 creerà una variabile temporanea (lato destro), quindi chiamare l'operatore di assegnazione per assegnare il valore di s

2 creerà un'istanza std::string sul mucchio e restituire un puntatore ad esso, e sarà fallire nell'assegnazione perché non è possibile assegnare un puntatore a un tipo non-pointer

3 costruirà uno std :: string e inizializzare da un const char*

+0

"non puoi assegnare un puntatore a un tipo non puntatore": secondo te quindi 'bool s; s = new std :: string ("Hello, world."); 'è un errore in fase di compilazione? BTW quel segno di uguale non è un compito (per esempio potrebbe essere legale scrivere 'Foo x = 12;' anche quando 'Foo :: operator = (int)' è privato). – 6502

+0

@ 6502: La sua formulazione è errata, ma in entrambi i casi non può essere assegnata da 'std :: string' –

+0

@MooingDuck: Questa risposta è semplicemente errata su alcuni punti: A) quelli non sono assegnazioni, sono inizializzazioni (in C++ è una cosa diversa, con regole diverse e semantica, l'operatore di assegnazione di cui parla parla in 1 è * NOT * chiamato), B) La frase "Non puoi assegnare un puntatore a un tipo non puntatore" è solo falso. .. puoi assegnare (e anche inizializzare) un valore booleano da un puntatore. Il punto 2 ha IMO una formulazione molto brutta in quanto sembra che stia dicendo che il codice verrà compilato e si otterrà un errore di runtime ... ma almeno c'è qualche dubbio che questo non è ciò che Fred intendeva. – 6502

0

Sul numero 1, si sta creando una temporanea stringa usando il costruttore e quindi assegnandolo a s. Il numero 2 non viene nemmeno compilato. Al numero 3, si sta creando una nuova stringa e quindi si assegna un valore.

3
std::string s = std::string("foo"); 

Si chiama inizializzazione della copia. È funzionalmente uguale inizializzazione diretta

std::string s("foo"); 

ma la prima richiede che il costruttore di copia è disponibile e compilatori può creare un oggetto temporaneo ma più elida temporanea e direttamente costruire s contenere "foo".


std::string s = new std::string("foo"); 

Questo non compilerà perché new restituisce un puntatore. Per farlo funzionare è necessario il tipo di s per essere un std::string *. Quindi la linea assegna dinamicamente un oggetto std::string e memorizza il puntatore in s. Avrai bisogno di delete una volta che hai finito di usarlo.


std::string s = "foo"; 

Questo è quasi la stessa di prima. È l'inizializzazione della copia ma ha un vincolo aggiunto. Richiede che la classe std::string contenga un costruttore non explicit che prende uno const char *. Ciò consente al compilatore di costruire implicitamente un oggetto temporaneo std::string. Dopo di che la semantica è identica al caso 1.