2013-10-04 8 views
5

Poniżej znajduje się kod znajdowania i zamiany ciągu podrzędnego na ciąg znaków.Ale nie jestem w stanie przekazać argumentów do funkcji.Błąd niepoprawnej inicjacji niezawartej referencji typu

Komunikat o błędzie:

invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string&}’ from an rvalue of type ‘const char*’

proszę o pomoc z wyjaśnieniem

#include <iostream> 
#include <string> 
using namespace std; 

void replaceAll(string &s, const string &search, const string &replace) { 
    for(size_t pos = 0; ; pos += replace.length()) { 
     pos = s.find(search, pos); 
     if(pos == string::npos) break; 
     s.erase(pos, search.length()); 
     s.insert(pos, replace); 
    } 
} 
int main() { 

    replaceAll("hellounny","n","k"); 
    return 0; 
} 
+1

Nie można powiązać tymczasowy do const odniesienia. Co ma się zmienić? – chris

+1

Tymczasowy oczywiście. Nigdy tak naprawdę nie zgadzałem się z tą zasadą, ale raz dostałem odpowiedź od samego Bjarne Stroustrupa, który powiedział, że pozwolił kodowi modyfikować tymczasowe pliki, jak to było "zbyt zagmatwane". – john

Odpowiedz

5

Uproszczony wyjaśnieniem jest to, że ponieważ czynność replaceAll zmienia łańcuch, trzeba nadać jej rzeczywisty ciąg zmiany.

int main() { 
    string str = "hellounny"; 
    replaceAll(str,"n","k"); 
    return 0; 
} 
+0

Uważam, że twoje "uproszczone wyjaśnienie" jest całkiem proste! – SimplyKnownAsG

1

To powinno usunąć błąd:

#include <iostream> 
#include <string> 
using namespace std; 

void replaceAll(string &s, const string &search, const string &replace) { 
    for(size_t pos = 0; ; pos += replace.length()) { 
     pos = s.find(search, pos); 
     if(pos == string::npos) break; 
     s.erase(pos, search.length()); 
     s.insert(pos, replace); 
    } 
} 
int main() { 

    string temp = "hellounny"; 
    replaceAll(temp,"n","k"); 
    return 0; 
} 
+1

To się zgadza. Jednak prawdziwe pytanie brzmi: dlaczego oryginalny kod jest błędem, a nie robi dokładnie to, co robi. To, co robi ten kod, jest tym, czego oczekuje użytkownik (byłoby bardziej oczywiste, gdyby replaceAll zwrócił kilka innych informacji, na przykład ile zostało zamienionych, tak aby miało sens, że kod chce zignorować zmodyfikowany ciąg znaków). – user3080602

1

Jeśli chcesz być w stanie przejść temporaries jako parametr, można powrócić wynik Zamiast:

std::string replaceAll(string s, const string &search, const string &replace) { 
    for(size_t pos = 0; ; pos += replace.length()) { 
     pos = result.find(search, pos); 
     if(pos == string::npos) break; 
     result.erase(pos, search.length()); 
     s.insert(pos, replace); 
    } 
    return s; 
} 

std::string result = replaceAll("hellounny", "n", "k"); 
0

Problem z Twój kod jest taki, że próbujesz odwołać się do obiektu tymczasowego, używając nie stałej odwołania. Kompilator tworzy tymczasowe obiekty do oceny ekspresji, aby tymczasowo przechowywać wartości obiektów (dla parametru pas śpiewaj, zwracaj wartości z func itp.). Możesz przypisać adres obiektu stałego do wskaźnika const, ponieważ po prostu obiecujesz, że nie zmienisz czegoś, co można zmienić. Ale nie można przypisać adresu obiektu const do odniesienia stałego, ponieważ pozwoli to później zmodyfikować obiekt. Prawidłowy sposób będzie używać zmiennej temp aby przekazać parametr

int main() 
{ 
    string temp = "This is a Temperory Var"; 
    replaceAll(temp,"n","k"); 
} 

jak @Umer i @john Wrote

+2

To trochę mylące wyjaśnienie. Problem nie polega na tym, że ciąg znaków w cudzysłowach jest stały, problem polega na tym, że łańcuchy w cudzysłowach nie są typu std :: string, więc kompilator musi skonstruować * tymczasowy * std :: string w celu wywołania funkcja, a reguła w C++ nie można powiązać niestanowiącego odniesienia odwołania do tymczasowego. Ta sama reguła zatrzymałaby ten kod kompilując 'string function_returning_a_string(); ... replaceAll (function_returning_a_string(), "n", "k"); "nawet jeśli w tym przypadku nie ma żadnych stałych. – john

+0

Thnx @john fr opracowanie :) – maximus

+0

Niestety tymczasowe nie są stałe. Na przykład ten kod jest legalny 'string function_returning_a_string(); ... function_returning_a_string() = "abc"; '. Zasadą jest, że nie można powiązać niezwiązanego z odwołaniem odniesienia do tymczasowego, niezależnie od tego, czy tymczasowe jest stałe, czy nie, nie ma znaczenia. Jeśli usuniesz "(co jest stałą)", to jest OK. – john