2009-07-24 14 views
19

Spotkałem dzisiaj interesującą sytuację w programie, w którym nieumyślnie przypisałem liczbę całkowitą bez znaku do std :: string. Kompilator VisualStudio C++ nie dawał żadnych ostrzeżeń ani błędów na jego temat, ale zdarzyło mi się zauważyć błąd, który wystąpił podczas uruchamiania projektu i dał mi niepotrzebne znaki dla mojego ciągu.Dlaczego C++ pozwala na przypisanie liczby całkowitej do ciągu?

To niby co kod wyglądało:

std::string my_string(""); 
unsigned int my_number = 1234; 
my_string = my_number; 

Poniższy kod kompiluje również dobrze:

std::string my_string(""); 
unsigned int my_number = 1234; 
my_string.operator=(my_number); 

następujące wyniki w błąd:

unsigned int my_number = 1234; 
std::string my_string(my_number); 

Co trwa? Jak to możliwe, że kompilator zatrzyma kompilację z ostatnim blokiem kodu, ale niech zbudują pierwsze 2 bloki kodu?

+0

Jakie są błędy kompilatora? Dla mnie g ++ v4.4 kompiluje się i działa poprawnie – CsTamas

+0

Przykro mi, popełniłem błąd z drugim blokiem kodu - to się kompiluje. Ostatni z nich kończy się niepowodzeniem z błędem dotyczącym braku konstruktora std :: string, który akceptuje unsigned int. – user55417

Odpowiedz

28

Ponieważ ciąg jest przypisywany od char, a int jest niejawnie wymienialny na char.

+0

Dlaczego int nie jest niejawnie rzutowany na ostatnie 2 bloki? Co masz na myśli, że nie mogę nazwać operatora = explicite? Ponieważ następujące prace: my_string.operator = ("Witaj świecie"); – user55417

+0

Czy nie 'moje_string.operator = (my_number)' jawne wywołanie 'operator ='? Co ja tu nie rozumiem? – sbi

+0

"Dlaczego int nie jest niejawnie rzutowany na ostatnie 2 bloki?" Ponieważ podczas gdy 1234 mieści się w 16 bitach, i może tam być char, nie każda unsigned int będzie pasowała do 16 bitów. Jak tylko określiłeś typ o większym zasięgu niż znak, zatrzymałeś kompilator od domyślnego rzucenia wartości do znaku. –

20

klasa std :: string ma następujący operator przypisania zdefiniowane:

string& operator=(char ch); 

Ten operator jest wywoływana przez niejawnej konwersji unsigned int do char.

W swoim trzecim przypadku używasz wyraźne konstruktora instancji std::string, żaden z dostępnych konstruktorów może zaakceptować unsigned int lub użyj niejawna konwersja z unsigned int:

string(); 
string(const string& s); 
string(size_type length, const char& ch); 
string(const char* str); 
string(const char* str, size_type length); 
string(const string& str, size_type index, size_type length); 
string(input_iterator start, input_iterator end); 
+3

"Operatorzy nie mogą być wywoływani przy użyciu składni wywołań funkcjonalnych". 13.5 (4) w standardzie C++ mówi, że mogą. –

+0

"Operatorzy nie mogą być wywoływani przy użyciu składni wywołań funkcjonalnych" To jest błędne. – sbi

+1

Wstyd, ponieważ przyjęta odpowiedź z początku popełniła ten sam błąd, ale mimo to została przegłosowana, a następnie poprawiona, podczas gdy ta odpowiedź jest znacznie lepsza i zostanie odrzucona. Będę głosować na to, jeśli zostanie to naprawione. –

2

Jest zdecydowanie operator = (char ch) call - mój debugger wkroczył w to. I mój MS VS 2005 kompiluje następujące bez błędu.

std::string my_string(""); 
unsigned int my_number = 1234; 
my_string = my_number; 
my_string.operator=(my_number); 
0

mogę wyjaśnić pierwsze i trzecie sytuacje:

my_string = 1234; 

To działa, ponieważ ciąg nadpisuje operatora = (char). W rzeczywistości przypisujesz znak (z przepełnieniem danych) do ciągu znaków. Nie wiem, dlaczego drugi przypadek powoduje błąd kompilacji. Próbowałem kodu z GCC i to się kompilowało.

std::string my_string(1234); 

nie będzie działać, ponieważ nie ma konstruktora ciągów, który pobiera argument char lub int.

Powiązane problemy