Jakie są zasady używania podkreślenia w identyfikatorze C++?
W C++ często nazywa się zmienne członkowskie jakimś prefiksem określającym fakt, że są to zmienne członkowskie, a nie zmienne lokalne lub parametry. Jeśli pochodzisz z tła MFC, prawdopodobnie użyjesz m_foo
. Widziałem też myFoo
okazjonalnie.
C #(lub ewentualnie po prostu. NET) wydaje się zalecać używanie tylko podkreślenia, jak w _foo
. Czy jest to dozwolone przez standard C++?
5 answers
Zasady (które nie zmieniły się w C++11):
- zastrzeżone w dowolnym zakresie, w tym do wykorzystania jako makra implementacyjne:
- identyfikatory rozpoczynające się podkreśleniem, a następnie od razu wielką literą
- identyfikatory zawierające sąsiadujące podkreślniki (lub"podwójny podkreślnik")
- zarezerwowane w globalnej przestrzeni nazw:
- identyfikatory zaczynające się od podkreślenia
- również wszystko w
std
przestrzeni nazw jest zastrzeżone. (Możesz jednak dodawać specjalizacje szablonów.)
Ze standardu C++ z 2003 roku:
Ponieważ C++ jest oparty na standardzie C (1.1/ 2, C++03) i C99 jest odniesieniem normatywnym (1.2/1, C++03), stosuje się je również od standardu C 1999:17.4.3.1.2 nazwy Globalne [lib.global.nazwy]
Niektóre zbiory nazw i podpisów funkcji są zawsze zarezerwowane dla implementacji:]}
- każda nazwa, która zawiera podwójny podkreślnik (
__
) lub zaczyna się podkreślnikiem, po którym następuje wielka litera (2.11), jest zarezerwowana dla implementacji do dowolnego użycia.- każda nazwa zaczynająca się od podkreślenia jest zarezerwowana dla implementacji do użycia jako nazwa w globalnej przestrzeni nazw.165
165) nazwy takie są również zarezerwowane w przestrzeni nazw
::std
(17.4.3.1).
7.1.3 zarezerwowane identyfikatory
Każdy nagłówek deklaruje lub definiuje wszystkie identyfikatory wymienione w powiązanej podkluczy, oraz opcjonalnie deklaruje lub definiuje identyfikatory wymienione w powiązanej z nimi przyszłej instrukcji bibliotecznej oraz identyfikatory, które są zawsze zarezerwowane do dowolnego wykorzystania lub do wykorzystania jako identyfikatory zakresu plików.
- wszystkie identyfikatory zaczynające się od podkreślenia i wielkiej litery lub innej podkreślenia są zawsze zarezerwowane do dowolnego użytku.
- wszystkie identyfikatory zaczynające się od podkreślenia są zawsze zarezerwowane do wykorzystania jako identyfikatory z zakresem plików zarówno w zwykłych, jak i nazwach znaczników.
- nazwa każdego makra w jednej z następujących podklauz (łącznie z przyszłą biblioteką directions) jest zarezerwowany do użycia, jak określono, jeśli którykolwiek z powiązanych nagłówków jest dołączony; o ile wyraźnie nie zaznaczono inaczej (zob. 7.1.4).
- wszystkie identyfikatory z linkami zewnętrznymi w jednej z następujących podklas (w tym przyszłych kierunków bibliotecznych) są zawsze zarezerwowane do wykorzystania jako identyfikatory z zewnętrznymi linkage.154
- każdy identyfikator z zakresem pliku wymienionym w jednej z następujących podklas (w tym przyszłe kierunki bibliotek) jest zarezerwowany do użycia jako nazwa makra i jako identyfikator z zakres pliku w tej samej przestrzeni nazw, jeśli którykolwiek z powiązanych nagłówków jest dołączony.
Żadne inne identyfikatory nie są zastrzeżone. Jeśli program deklaruje lub definiuje identyfikator w kontekst, w którym jest zarezerwowany (inny niż dozwolony przez 7.1.4), lub definiuje zastrzeżone identyfikator jako nazwa makra, zachowanie jest niezdefiniowane.
Jeśli program usunie (z
#undef
) dowolną definicję makra identyfikatora w pierwszym Grupa wymieniona powyżej, zachowanie jest niezdefiniowane.154) lista zastrzeżonych identyfikatorów z powiązaniem zewnętrznym obejmuje
errno
,math_errhandling
,setjmp
, iva_end
.
Mogą obowiązywać inne ograniczenia. Na przykład standard POSIX rezerwuje wiele identyfikatorów, które są prawdopodobnie pojawi się w normalnym kodzie:
- Nazwy zaczynające się od wielkiej litery
E
po cyfrze lub Wielkiej literze:- Może być używany dla dodatkowych nazw kodów błędów.
- Nazwy zaczynające się na
is
lubto
, po których następuje mała litera- Może być używany do dodatkowych testów znaków i funkcji konwersji.
- Nazwy zaczynające się na
LC_
, po których następuje wielka litera- Może być stosowany do dodatkowe makra określające atrybuty lokalne.
- nazwy wszystkich istniejących funkcji matematycznych zakończone
f
lubl
są zastrzeżone- dla odpowiednich funkcji operujących odpowiednio na argumentach float i long double.
- nazwy rozpoczynające się od
SIG
, po której następuje wielka litera są zastrzeżone- dla dodatkowych nazw sygnałów.
- Nazwy zaczynające się na
SIG_
, po których następuje wielka litera są zastrzeżone- dla dodatkowych akcji sygnałowych.
- Nazwy zaczynające się na
str
,mem
, lubwcs
, po których następuje mała litera są zarezerwowane- dla dodatkowych funkcji typu string i array.
- nazwy rozpoczynające się od
PRI
lubSCN
, po których następuje mała litera lubX
są zarezerwowane- dla dodatkowych makr specyfikacji formatu
- nazwy kończące się na
_t
są zastrzeżone- dla dodatkowe nazwy typów.
Chociaż używanie tych nazw do własnych celów w tej chwili może nie powodować problemu, to jednak podnoszą one możliwość konfliktu z przyszłymi wersjami tego standardu.
Osobiście po prostu nie zaczynam identyfikatorów od podkreślenia. Nowy dodatek do mojej zasady: nie używaj podwójnego podkreślenia nigdzie, co jest łatwe, ponieważ rzadko używam podkreślenia.
Po przeprowadzeniu badań nad tym artykułem nie kończę już moich identyfikatorów z _t
ponieważ jest to zarezerwowane przez standard POSIX.
Zasada o każdym identyfikatorze kończącym się na _t
bardzo mnie zaskoczyła. Myślę, że jest to standard POSIX (jeszcze nie jestem pewien) szukający wyjaśnienia i oficjalnego rozdziału i wersetu. To jest z GNU libtool manual , listing nazw zastrzeżonych.
CesarB dostarczył następujący link do POSIX 2004 zarezerwowanych symboli i notatek ' oraz wielu innych zarezerwowanych przedrostków i sufiksów ... można tam znaleźć". Na POSIX 2008 symbole Zastrzeżone są tutaj zdefiniowane. Ograniczenia są nieco bardziej niuansowane niż te powyżej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 12:04:38
Zasady unikania kolizji nazw są zarówno w standardzie C++ (patrz Księga Stroustrupa), jak i wspomniane przez Guru C++ (Sutter itp.).
Reguła osobista
Ponieważ nie chciałem zajmować się sprawami i chciałem prostej zasady, zaprojektowałem osobisty taki, który jest zarówno prosty, jak i poprawny:
Podczas nazywania symbolu unikniesz kolizji z bibliotekami kompilatora / OS / standard, jeśli:
- nigdy nie zaczynaj symbolu z podkreślenie
- nigdy nie nazywaj symbolu z dwoma kolejnymi podkreślnikami wewnątrz.
Oczywiście umieszczenie kodu w unikalnej przestrzeni nazw również pomaga uniknąć kolizji (ale nie chroni przed złymi makrami)
Niektóre przykłady
(używam makr, ponieważ są one bardziej zanieczyszczające kod symboli C / C++, ale może to być cokolwiek od nazwy zmiennej do nazwy klasy)
#define _WRONG
#define __WRONG_AGAIN
#define RIGHT_
#define WRONG__WRONG
#define RIGHT_RIGHT
#define RIGHT_x_RIGHT
Extracts from C++0x draft
Z n3242.plik pdf (oczekuję końcowy standardowy tekst podobny):
17.6.3.3.2 nazwy Globalne [global.nazwy]
Niektóre zestawy nazw i podpisów funkcji są zawsze zarezerwowane dla implementacji:
- każda nazwa, która zawiera podwójny podkreślnik _ _ lub zaczyna się od podkreślnika, po którym następuje wielka litera (2.12), jest zarezerwowana dla implementacji do dowolnego użycia.
- każda nazwa zaczynająca się od podkreślenia jest zarezerwowana dla implementacji do użycia jako nazwa w globalnej przestrzeni nazw.
Ale także:
17.6.3.3.5 user-defined dosłowne sufiksy [usrlit.sufiks]
Dosłowne identyfikatory sufiksów, które nie rozpoczynają się podkreśleniem, są zarezerwowane dla przyszłej standaryzacji.
Ta ostatnia klauzula jest myląca, chyba że uznasz, że nazwa zaczynająca się od podkreślenia i poprzedzona małą literą byłaby w porządku, gdyby Nie zdefiniowano w globalnej przestrzeni nazw...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-27 20:32:18
From MSDN :
Użycie dwóch sekwencyjnych znaków podkreślenia ( _ _ ) na początku identyfikatora lub pojedynczego głównego podkreślenia, po którym następuje wielka litera, jest zarezerwowane dla implementacji C++ we wszystkich zakresach. Należy unikać używania jednego głównego podkreślenia, po którym następuje mała litera dla nazw z zakresem plików z powodu ewentualnych konfliktów z obecnymi lub przyszłymi zastrzeżonymi identyfikatorami.
Oznacza to, że można użyć pojedynczego podkreślenia jako prefiks zmiennej członkowskiej, o ile po nim następuje mała litera.
Jest to najwyraźniej zaczerpnięte z sekcji 17.4.3.1.2 standardu C++, ale nie mogę znaleźć oryginalnego źródła dla pełnego standardu online.
Zobacz też to pytanie .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:50
Jeśli chodzi o drugą część pytania, powszechne jest umieszczanie podkreślenia na końcu nazwy zmiennej, aby nie kolidować z niczym wewnętrznym.
Robię to nawet wewnątrz klas i przestrzeni nazw, ponieważ wtedy muszę zapamiętać tylko jedną regułę(w porównaniu do "na końcu nazwy w zasięgu globalnym, a na początku nazwy wszędzie indziej").
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-01 16:10:18
Tak, podkreślniki mogą być używane w dowolnym miejscu identyfikatora. Wydaje mi się, że zasady są następujące: dowolne z a-z, a-z, _ w pierwszym znaku i te + 0-9 dla kolejnych znaków.
Prefiksy podkreślenia są powszechne w kodzie C-pojedynczy podkreślnik oznacza "prywatny", a podwójne podkreślenia są zwykle zarezerwowane do użycia przez kompilator.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-23 07:05:58