2014-11-17 2 views
8

Ho appena incontrato qualche incomprensione: almeno in libC++ realizzazione std :: :: sperimentale string_view ha la seguente implementazione concisa:comportamento string_view quando passa std :: string temporanea

template <class _CharT, class _Traits....> 
class basic_string_view { 
public: 
    typedef _CharT value_type; 
    ... 
    template <class _Allocator> 
    basic_string_view(const basic_string<_CharT, _Traits, _Allocator>& str): 
     __data(str.data()), __size(str.size()) 
    { 
    } 

private: 
    const value_type* __data; 
    size_type __size; 
}; 

Questo implementazione implica che se passiamo un'espressione rvalue a questo costruttore, otterremo un comportamento indefinito quando usiamo __data dopo la costruzione?

+1

Già. Un 'string_view' è solo un riferimento glorificato. – Rapptz

+1

[Vedi anche] (http://stackoverflow.com/q/20803826/596781). –

risposta

13

Proprio così. A string_view è un wrapper non proprietario con semantica di riferimento che deve essere utilizzato solo quando la stringa indicata sopravvive all'utilizzo della vista.

Il tipico caso d'uso è in parametri di funzione in cui la stringa effettiva vive per tutta la durata della chiamata di funzione e il corpo della funzione non memorizza la vista, ma solo legge esso:

void foo(std::experimental::string_view message) // pass by value 
{ 
    std::cout << "You said, '" << message << "'.\n"; 
} 

Usage:

foo("Hello");  // OK, string literal has static storage 
foo(s);    // OK, s is alive 
foo(s.substr(1)); // OK, temporary lives until end of full-expression 

la morale è: Se avete solo bisogno la stringa per tutta la durata del corpo della funzione, la funzione di dare un parametro string_view, e può legarsi in modo uniforme a qualsiasi tipo di argume stringoid nt. Non è necessario un modello di funzione, la copia di string_view s è economica e si ottengono gratuitamente alcune operazioni di sottostringa. Al contrario, mai memorizzare una string_view, ma sempre memorizzare un string:

struct X 
{ 
    X(std::experimental::string_view s) : s_(s) {} 

    std::string s_;  // NEVER have a string_view class member! 
}; 
+1

"Mai" è un po 'duro, ma se lo si memorizza, è necessario fare la stessa cura che si farebbe se si memorizza un "char *" – plugwash

+1

@plugwash: Forse. Ma direi che faresti sicuramente un messaggio non ufficiale se hai archiviato la vista. Sì, in una classe transitoria che è usata solo come prvalore potreste * essere in grado di farne uso, ma tale codice è probabilmente scritto meglio con lambda che chiarisce che la stringa visualizzata sopravvive al chiamabile. –