2016-03-10 10 views
5

ero alla ricerca di esempi su come fare qualcosa e visto questo due varianti:Qual è la differenza tra "std :: string const & s" e "const std :: string & s"?

std::string const &s; 
const std::string &s; 

in diversi frammenti.

thx per la risposta :)

+6

Non c'è differenza, semanticamente. Solo una domanda su quale stile preferisce. –

+1

Nel primo 's' è un riferimento a una stringa costante. Nel secondo 's' c'è un riferimento a una stringa che è costante. Cioè entrambi sono davvero gli stessi. –

+3

Argomenti correlati: http://stackoverflow.com/questions/5503352/const-before-or-const-after http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int -const-int-const-and-int-const – dragosht

risposta

5

Tecnicamente è lo stesso e non fa alcuna differenza. Ma in alcuni debugger (lldb di sicuro) vedrete std::string const& anche se avete scritto come const std::string&.

2

solo per dimostrare altre assertations persone (capisco che RTTI non prende constness o voltilness nel .name() uscita)

questo programma di test:

#include "stdafx.h" 
#include <string> 
#include <iostream> 

using std::string; 
using std::cout; 
using std::cin; 

    using std::endl; 

    int _tmain(int argc, _TCHAR* argv[]) 
    { 
    std::string t = "BLABLA" ; 
    std::string t1 = "BLABLA" ; 
    std::string const &s = t; 
    const std::string &d = t1; 


if (typeid(d) == typeid(s)) 
    cout << "d and s are the same type according to the rtti" << endl; 

else 
    cout << "d and s are the NOT the same type according to the rtti" << endl; 
    // here the raw output is exactly the same for both 
    cout << typeid(d).raw_name() << endl << typeid(s).raw_name() << endl; 

    cin >> t; 
    return 0; 
} 

sia per gcc (4.9.2) (con le opportune modifiche) msdn (vs2010) restituisce "stesso tipo" per entrambi.

Io scopo questa "risposta" come un contributo e non come una "risposta".

MODIFICA: L'elemento di lettura 4 in "Effective Modern C++" di Scott-Meyers condivide alcune informazioni nascoste davvero interessanti sull'esempio che ho scritto. In breve, typeid non fornisce risultati affidabili dal stiamo passando nomi variabili per il valore. Quando passiamo a un metodo una variabile per valore, il tipo dedotto perde la sua costanza, volatilità e referenza (perché l'amore di dio sarà abbreviato in cvr). Ecco perché l'esempio sopra non dimostra se c'è differenza tra i due tipi.

Lo stesso articolo indica che il progetto Boost ospita una libreria denominata TypeIndex, che conserva le proprietà del cvr.

+0

Downvoters, dimmi perché! – Aviv

+2

Downvoters - Ho trovato il nostro dove mi sbagliavo, con poco o nessun grazie a te. – Aviv

5

std::string const & è equivalente a const std::string &.

const std::string & è lo stile adottato in Stroustup Il linguaggio di programmazione C++ e probabilmente è "lo stile tradizionale".

std::string const & può essere più coerente che l'alternativa:

il const-on-the-destra stile mette sempre il const a destra di quello che constifies, mentre l'altro stile a volte mette la const sulla a sinistra ea volte a destra.

Con lo stile const-on-the-right, una variabile locale che const è definita con const sulla destra: int const a = 42;. Allo stesso modo una variabile statica const è definita come static double const x = 3.14;. Fondamentalmente, ogni const finisce sulla destra della cosa che protegge, incluso lo const che è necessario essere sulla destra: con una funzione membro const.

(vedere What do “X const& x” and “X const* p” mean? per ulteriori dettagli).

Se si decide di utilizzare const-on-the-destra stile, assicuratevi di non mis-tipo std::string const &s come insensata std::string & const s:

La dichiarazione di cui sopra significa: "s è un const riferimento ad un std::string ". È ridondante poiché i riferimenti sono sempre const (non è mai possibile reimpostare un riferimento per fare in modo che si riferisca a un oggetto diverso).

1

Come indicato, sono dello stesso tipo. Uno dei motivi per cui piace il const a destra è come gioca con i modelli. La maggior parte delle persone elabora i modelli di funzione semplicemente sostituendo. Per esempio:

template <class T> void foo(const T& arg); 

int* p; 
foo(p); 

Qual è il tipo di arg? Si desidera dire const int*&, ovvero un riferimento a un puntatore a const int, ma è errato. La sostituzione del testo ti ha deluso. Se si ha scritto invece come

template <class T> void foo(T const& arg); 

Poi semplice sostituzione di testo produce il tipo corretto: int* const&. Cioè, un riferimento al puntatore const a int.

0

Come ha notato Barry in his answer, la vecchia sintassi C (e l'estensione C++ di tale sintassi) non supporta la visualizzazione concettuale della sostituzione del testo, come in matematica.

Utilizzando la sintassi C direttamente è quindi generalmente una buona idea per scrivere T const, non const T, anche se, quando T è un tipo semplice queste espressioni tipo sono equivalenti. La scrittura T const evita inoltre incoerenze in una dichiarazione di puntatore multilivello come char const* const p;, in cui non è possibile spostare l'ultimo const. Che esemplifica che l'equivalenza è solo per il tipo di base all'inizio di una dichiarazione.

Alcuni mesi fa ho iniziato un esperimento scrivendo const T e utilizzando tale notazione in modo coerente. Perché ora è possibile dopo C++ 11, senza usare macro. Per sostenere la consistenza che uso chiamato tipo costruttori come

template< class Some_type > 
using Ptr_ = Some_type*; 

in modo che al posto della lettura da destra a sinistra

char const* const p = something; 

posso e non scrivere la direzione di lettura ordinaria

const Ptr_<const char> p = something; 

E 'po' più prolisso, ma ora, con una certa esperienza di usarlo, credo che sia valsa la pena (non ero sicuro di questo, è stato un experime nt).

Lo svantaggio principale è che mentre questa notazione supporta la deduzione dei tipi per argomenti della funzione (modello di funzione) proprio come l'uso diretto della sintassi C, non supporta la deduzione di tipo per le dichiarazioni auto. Fortunatamente, poiché un inizializzatore può essere facilmente realizzato const, l'unico caso problematico riguarda l'array.La mia soluzione pragmatica finora è stata quella di usare la sintassi C (o meglio, C++) direttamente in questi casi, ma penso che ciò rappresenti una lacuna o un buco nel linguaggio, possibilmente con qualche soluzione generale che renderebbe le cose molto più facili anche in altri contesti.

Per i miei builder di tipo corrente come Ptr_, vedere the cppx/core_language_support/type_builders.hpp file at Github. Includono per es. In_ per gli argomenti della funzione. E sì, ho trovato che ne vale anche la pena, per chiarezza, nonostante qualche verbosità, perché rende l'intento molto chiaro. Tuttavia, le informazioni su cppx sono sperimentali e soggette a modifiche. Il file specifico collegato a qui può anche essere spostato, ma sarà a distanza. :)