2015-12-08 25 views
8

Quindi, operator[] non dice direttamente che s[s.size()] deve essere il carattere dopo s[s.size()-1] nella memoria. Sembra formulato per evitare di fare questa affermazione.Can `std :: basic_string :: operator []` può restituire un terminatore nul "distante" protetto?

Ma s.data() indica che s.data()+k == &s[k] e s.data() devono restituire un puntatore.

Ignorando il difetto livello apparente di utilizzare & su CharT sopra e non std::addressof, è l'implementazione libera per restituire un diverso CharT (ad esempio, uno su una pagina protetta, o in ROM) per s[s.size()] prima della prima chiamata a s.data() ? (Chiaramente si potrebbe organizzare il buffer di porre fine ad una pagina di sola lettura con uno zero su di esso, sto parlando di una situazione diversa)

Per essere espliciti:

Per quanto posso dire, se s.data() non viene mai chiamato (e il compilatore può provarlo), quindi s[s.size()] non deve essere contiguo con il resto del buffer.

Può std::addressof(s[s.size()])cambiamento dopo una chiamata al s.data() e l'attuazione risulti conforme agli standard (fino a quando s.data()+k == &s[k] ha .data() valutati prima [], ma il compilatore è libero di far rispettare quello). O ci sono requisiti di immutabilità che non riesco a vedere?

+0

cppreference dice chiaramente che dal momento che C++ 11 'operator []' si comporta esattamente come si descrive per 'data().' Tuttavia, si dice anche che questo carattere non può essere modificato. – SergeyA

+1

@SergeyA La dicitura precedente è la mia lettura dello standard (corrente bozza), piuttosto che basare l'interpretazione di qualcun altro (chiunque abbia modificato per ultimo, per esempio). Se vuoi, posso aggiungere citazioni dirette, ma non sono difficili da trovare (apri il tuo standard, cerca 'basic_string', vai ad esso dall'indice, cerca' operator ['e' data ('da lì). Mi chiedo se ci siano * altre * restrizioni che mi sono sfuggite (come inizialmente mi mancava la restrizione implicita '.data()' su '& s [s.size()]'). La maggior parte di quelle ovvie (basate sugli iteratori) don si applica, poiché '* s.end()' rimane UB. – Yakk

+0

Lo standard indica effettivamente che 's [s.size()]' è ben definito e non UB? È oltre la fine della stringa dopo tutto e sarebbe UB per qualsiasi altro contenitore.In pratica è probabile che ogni implementazione tenga il null finale richiesto da 'c_str()' quindi è probabilmente un punto controverso –

risposta

1

Poiché C++ 11, std :: string è necessario per essere memorizzato nella memoria contigua. Questa è la citazione dallo standard C++ 11 (sezione 24.4.1.4):

Gli oggetti char-simili in un basic_string oggetto sono memorizzati in modo contiguo. Cioè, per qualsiasi basic_string oggetto s , l'identità & * (s.begin() + n) == & * s.begin() + n terrà a tutti i valori di n tale che < = n < s.size() .

Questa citazione circa il valore di ritorno dell'operatore [] afferma che restituisce lo stesso &*(s.begin()+n) (sezione 21.4.5.1):

* (begin() + pos) se pos < dimensione() . Altrimenti, restituisce un riferimento a un oggetto di tipo Grafico con valore grafico() , dove modificare l'oggetto porta ad un comportamento indefinito

Poi abbiamo questa citazione sul valore restituito di dati() a (sezione 24.4.7.1):

Un puntatore p tali che p + i == & operatore [] (i) per ogni i in [0, dimensioni()] .

Quindi i dati restituiscono lo stesso come si otterrebbe utilizzando l'operatore & []. E qualsiasi valore tra voi recuperare utilizzando l'operatore & deve essere memorizzato in modo contiguo. Quindi è possibile concludere sia restituire un puntatore alla memoria contigua. Quindi non restituirà un puntatore a una pagina di distanza.

Si noti che questo si applica solo a C++ 11. Tali garanzie non sono state fatte dallo standard prima del C++ 11.

+0

Dovrebbe essere risolto ora. – Shadowwolf

+1

La prima e la seconda citazione escludono espressamente il caso in cui 'n == s.size()' o 'pos == size()'. – user2357112

+2

@Yakk: la parte della seconda citazione che supporta l'affermazione che 'operator []' restituisce un riferimento a '* (s.begin() + n)' esclude il caso in cui 'n == s.size()'. – user2357112