2014-12-09 8 views
7

Utilizzo Visual Studio 2013 per lo sviluppo, che utilizza la v12 degli strumenti di compilazione C++ di Microsoft.
Il seguente codice viene eseguito bene, la stampa "foo" per la console:Perché la funzione regex_match di C++ richiede che la stringa di ricerca sia definita al di fuori della funzione?

#include <regex> 
#include <iostream> 
#include <string> 

std::string get() { 
    return std::string("foo bar"); 
} 

int main() { 
    std::smatch matches; 
    std::string s = get(); 
    std::regex_match(s, matches, std::regex("^(foo).*")); 
    std::cout << matches[1] << std::endl; 
} 
// Works as expected. 

Lo stesso codice, con la stringa "s" sostituito per la funzione "get()", lancia una "stringa iteratori incompatibile" errore in fase di esecuzione:

#include <regex> 
#include <iostream> 
#include <string> 

std::string get() { 
    return std::string("foo bar"); 
} 

int main() { 
    std::smatch matches; 
    std::regex_match(get(), matches, std::regex("^(foo).*")); 
    std::cout << matches[1] << std::endl; 
} 
// Debug Assertion Failed! 
// Expression: string iterators incompatible 

Questo non ha senso per me. Qualcuno può spiegare perché questo accade?

+0

Funziona per me, ma ci sono in effetti due sovraccarichi per lvalue e rvalue 'string's ... forse uno di questi è collegato a una vostra implementazione? – Columbo

+1

Stai usando gcc? O una diversa implementazione regex? Ho provato questo con l'anteprima di Visual Studio 2015, che utilizza v14 degli strumenti del compilatore e si verifica lo stesso errore. – slbelden

risposta

10

Il motivo è che get() restituisce una stringa temporanea, quindi i risultati della corrispondenza contengono gli iteratori in un oggetto che non esiste più e il tentativo di utilizzarli è un comportamento non definito. Le asserzioni di debug nella libreria Visual Studio C++ notano questo problema e interrompono il programma.

Originariamente C++ 11 hanno permesso quello che stai cercando di fare, ma perché è così pericoloso è stata impedita l'aggiunta di un sovraccarico cancellato di std::regex_match che viene usato quando si cerca di ottenere i risultati delle partite da una stringa temporanea, vedere LWG DR 2329. Ciò significa che il tuo programma non dovrebbe essere compilato in C++ 14 (o nei compilatori che implementano il DR anche in modalità C++ 11). GCC non ha ancora implementato il cambiamento, lo aggiusterò.

+1

Ah, questo ha senso! La rimozione della linea di cout consente al codice di funzionare correttamente. Avevo dimenticato che std :: smatch memorizza solo i riferimenti ai risultati, non i risultati stessi. – slbelden

+2

Lavavej l'ha anche menzionato nel suo discorso su cppcon su http://youtu.be/dTeKf5Oek2c?t=41m50s. Ho trovato il discorso abbastanza buono da guardare. –

Problemi correlati