2013-03-12 22 views
13

Według standardu C++ ciąg typ dosłowny jest array of const charC++ const poprawności z napisowych

auto constStr = "aaa"; 
char* nonConstStr = constStr; //Error here, cannot convert from 'const char *' to 'char *' 
char* stillNonConstStr = "aaa"; //Why I don't have error here? 

Czy możesz mi wyjaśnić, dlaczego na 3 linii I nie pojawia się błąd?

+1

@Rapptz Nie mogę znaleźć takiej samej klauzuli zezwalającej na taką samą "wsteczną kompatybilność" w standardzie C++ 11. Sądzę, że został usunięty, więc powiązane pytanie nie jest obecnie duplikatem. – Angew

+0

Ponieważ lepiej jest pozwolić na to, ponieważ historycznie zostało to dozwolone, niż rozbicie tysięcy istniejących programów. –

+3

@Rapptz Jak jest pytanie + odpowiedź na temat C duplikatu jednego o C++? Zwłaszcza w obszarze, w którym oba języki faktycznie się różnią. – Angew

Odpowiedz

12

W C++ 03 istniała specjalna reguła ([conv.array] §2), która umożliwia konwertowanie literałów łańcuchowych na typ char*.

W C++ 11 ta reguła już nie istnieje. Innymi słowy, twój kod jest poprawny C++ 03, ale nieprawidłowy C++ 11.

+0

* źle sformułowany * lub * wycofany * C++ 11. Nie jest nieważny. Nadal byłoby to kompilować z przyczyn historycznych. [Zobacz tutaj bez -Wall] (http://ideone.com/Itv8Hz) lub [tutaj z -Wall-Werror] (http://coliru.stacked-crooked.com/view?id=bf8d5e2bc40d1220813841a85bfdbe25-18aa934a8d82d638dde2147aa94cac94) – Rapptz

+7

@ Rapptz: illformed == invalid. –

+2

@Rapptz Uwaga, * zepsuty *! = * Przestarzały *, * "przestarzały" * rzeczy działają, ale są zniechęcane, * "zniekształcone" * (i * "nieprawidłowe" *, jak * Benjamin * mówi) rzeczy * nie * praca. –

14

Powody historyczne. Kiedyś dozwolone i bardzo powszechne było przypisywanie z literału ciągu do char*, mimo że typ literału łańcuchowego jest tablicą znaków stałych. Wierzę, że pochodzi z dni C gdzie const nie istnieje, ale nie cytuj mnie na ten temat. Został później przestarzały, ale nadal dozwolony, aby nie łamać baz kodów, które go używały. To ograniczenie nie pozwala na zainicjowanie char* z const char* (ani z tablic const char, które nie są literałami), dlatego twoja druga linia zawodzi. W języku C++ 11 konwersja z literału łańcuchowego na char* jest zabroniona, ale twój kompilator może jeszcze tego nie wymusić.