Żadnej miłości do C ++, jeśli chodzi o linię pytań „ukrytych funkcji”? Pomyślałem, że to tam wyrzucę. Jakie są ukryte funkcje C ++?
c++
hidden-features
Craig H
źródło
źródło
Odpowiedzi:
Większość programistów C ++ zna operator trójskładnikowy:
Jednak nie zdają sobie sprawy, że można go użyć jako lwartości:
co jest skrótem dla
Używaj ostrożnie :-)
źródło
(value ? function1 : function2)()
.function1
ifunction2
są niejawnie konwertowane na wskaźniki funkcji, a wynik jest niejawnie konwertowany z powrotem.Możesz umieścić URI w źródle C ++ bez błędów. Na przykład:
źródło
goto
którą ma C ++). Cokolwiek po dwóch ukośnikach jest komentarzem. Dlatego zhttp://stackoverflow.com
,http
jest etykietą (teoretycznie można by to napisaćgoto http;
) i//stackoverflow.com
jest to tylko komentarz na końcu linii. Oba są legalnym C ++, więc konstrukcja jest kompilowana. Oczywiście nie robi to niczego pożytecznego.goto http;
rzeczywistości nie podąża za adresem URL. :(Programiści C ++ wolą unikać wskaźników z powodu błędów, które można wprowadzić.
Jednak najfajniejszy C ++, jaki kiedykolwiek widziałem? Literały analogowe.
źródło
Zgadzam się z większością tamtejszych postów: C ++ jest językiem wieloparadygmatycznym, więc „ukryte” funkcje, które znajdziesz (inne niż „niezdefiniowane zachowania”, których powinieneś unikać za wszelką cenę) to sprytne wykorzystanie udogodnień.
Większość z tych udogodnień nie jest wbudowanymi funkcjami języka, ale są oparte na bibliotekach.
Najważniejszy jest RAII , często ignorowany przez lata przez programistów C ++ pochodzących ze świata C. Przeciążanie operatorów jest często niezrozumianą funkcją, która umożliwia zarówno zachowanie tablicowe (operator indeksu dolnego), operacje podobne do wskaźnika (inteligentne wskaźniki), jak i operacje podobne do wbudowanych (mnożenie macierzy).
Zastosowanie wyjątku jest często trudne, ale przy odrobinie pracy może stworzyć naprawdę solidny kod dzięki zabezpieczeniu wyjątków specyfikacjom (w tym kod, który nie zawiedzie lub będzie miał funkcje podobne do zatwierdzania, które się powiodą lub powrócą do jego pierwotny stan).
Najbardziej znaną „ukrytą” funkcją C ++ jest metaprogramowanie szablonów , ponieważ pozwala ono na częściowe (lub całkowite) wykonanie programu w czasie kompilacji zamiast w czasie wykonywania. Jest to jednak trudne i zanim spróbujesz, musisz dobrze opanować szablony.
Inne wykorzystują paradygmat wielu do tworzenia „sposobów programowania” spoza przodka C ++, to znaczy C.
Używając funktorów , można symulować funkcje, z dodatkowym zabezpieczeniem typu i stanem. Używając wzorca polecenia , możesz opóźnić wykonanie kodu. Większość innych wzorców projektowych można łatwo i wydajnie zaimplementować w C ++ w celu stworzenia alternatywnych stylów kodowania, których nie powinno się znajdować na liście „oficjalnych paradygmatów C ++”.
Korzystając z szablonów , możesz stworzyć kod, który będzie działał na większości typów, w tym na innym niż ten, o którym myślałeś na początku. Możesz także zwiększyć bezpieczeństwo typów (np. Zautomatyzowany malloc / realloc / free). Funkcje obiektu C ++ są naprawdę potężne (a zatem niebezpieczne, jeśli są używane niedbale), ale nawet dynamiczny polimorfizm ma swoją statyczną wersję w C ++: CRTP .
Odkryłem, że większość książek typu „ Efektywny C ++ ” autorstwa Scotta Meyersa lub „ Wyjątkowy C ++” ” autorstwa Herba Suttera jest zarówno łatwa do czytania, jak i skarbnica informacji o znanych i mniej znanych cechach C ++.
Jednym z moich ulubionych jest taki, który powinien sprawić, że włosy każdego programisty Java wyrosną z horroru: w C ++ najbardziej obiektowym sposobem dodania funkcji do obiektu jest użycie funkcji niebędącej składową nieprzyjazną, zamiast funkcja (czyli metoda klasowa), ponieważ:
W C ++ interfejs klasy to zarówno jej funkcje składowe, jak i funkcje niebędące składowymi w tej samej przestrzeni nazw
nieprzyjazne funkcje niebędące członkami nie mają uprzywilejowanego dostępu do wewnętrznej klasy. W związku z tym użycie funkcji składowej zamiast nieprzyjaznej, niebędącej składnikiem, osłabi hermetyzację klasy.
To zawsze zaskakuje nawet doświadczonych programistów.
(Źródło: między innymi, internetowy Guru tygodnia Herba Suttera nr 84: http://www.gotw.ca/gotw/084.htm )
źródło
Jedną z funkcji języka, którą uważam za nieco ukrytą, ponieważ nigdy o niej nie słyszałem przez cały czas w szkole, jest alias przestrzeni nazw. Nie zwróciłem na to mojej uwagi, dopóki nie natknąłem się na przykłady w dokumentacji boost. Oczywiście, skoro już o tym wiem, możesz go znaleźć w każdym standardowym dokumencie C ++.
źródło
using
.W części init
for
pętli można deklarować nie tylko zmienne , ale także klasy i funkcje.To pozwala na wiele zmiennych różnych typów.
źródło
Operator tablicy jest asocjacyjny.
A [8] jest synonimem * (A + 8). Ponieważ dodawanie jest asocjacyjne, można to przepisać na * (8 + A), co jest synonimem ..... 8 [A]
Nie powiedziałeś przydatnych ... :-)
źródło
A
nie ma żadnego znaczenia. Na przykład, gdybyA
był achar*
, kod nadal byłby ważny.Niewiele wiadomo, że związki mogą być również szablonami:
Mogą też mieć konstruktory i funkcje składowe. Po prostu nie ma nic wspólnego z dziedziczeniem (w tym funkcjami wirtualnymi).
źródło
From
iTo
są odpowiednio ustawione i używane. Taka unia może być jednak używana ze zdefiniowanym zachowaniem (To
jako tablica bez znaku lub struktura dzieląca sekwencję początkowąFrom
). Nawet jeśli używasz go w nieokreślony sposób, może być przydatny do pracy na niskim poziomie. W każdym razie to tylko jeden przykład szablonu unii - mogą istnieć inne zastosowania unii opartej na szablonach.C ++ jest językiem wieloparadygmatycznym, możesz postawić ostatnie pieniądze na ukryte funkcje. Jeden z wielu przykładów: metaprogramowanie szablonów . Nikt w komitecie normalizacyjnym nie chciał, aby język uzupełniający Turinga był wykonywany w czasie kompilacji.
źródło
Inną ukrytą funkcją, która nie działa w C, jest funkcjonalność jednostki jednoargumentowej
+
operatora . Możesz go używać do promowania i niszczenia różnych rzeczyKonwersja wyliczenia na liczbę całkowitą
A wartość modułu wyliczającego, która wcześniej miała swój typ wyliczenia, ma teraz doskonały typ liczby całkowitej, który może pasować do jego wartości. Ręcznie prawie nie znasz tego typu! Jest to potrzebne na przykład wtedy, gdy chcesz zaimplementować przeciążony operator do wyliczenia.
Uzyskaj wartość ze zmiennej
Musisz użyć klasy, która używa statycznego inicjatora w klasie bez definicji poza klasą, ale czasami nie można jej połączyć? Operator może pomóc w utworzeniu tymczasowego bez robienia założeń lub zależności od jego typu
Rozpad tablicę na wskaźnik
Czy chcesz przekazać dwa wskaźniki do funkcji, ale to po prostu nie zadziała? Operator może pomóc
źródło
Niewiele osób wie o czasie życia tymczasowych obiektów tymczasowych powiązanych z odniesieniami do stałych. A przynajmniej jest to moja ulubiona część wiedzy C ++, o której większość ludzi nie wie.
źródło
Przyjemną funkcją, która nie jest często używana, jest blok try-catch obejmujący całą funkcję:
Głównym zastosowaniem byłoby przetłumaczenie wyjątku na inną klasę wyjątków i ponowne zgłoszenie lub tłumaczenie między wyjątkami i obsługą kodu błędu opartego na zwracaniu.
źródło
return
z catch bloku Function Try, tylko powtórz.Wiele osób zna
identity
/id
metafunkcję, ale jest dla niej niezły przypadek użycia dla przypadków innych niż szablony: Łatwość pisania deklaracji:Bardzo pomaga odszyfrować deklaracje C ++!
źródło
template<typename Ret,typename... Args> using function = Ret (Args...); template<typename T> using pointer = *T;
->pointer<function<void,int>> f(pointer<function<void,void>>);
lubpointer<void(int)> f(pointer<void()>);
lubfunction<pointer<function<void,int>>,pointer<function<void,void>>> f;
Dość ukrytą funkcją jest to, że możesz definiować zmienne w ramach warunku if, a jego zakres będzie obejmował tylko bloki if i else:
Niektóre makra tego używają, na przykład w celu zapewnienia pewnego „zablokowanego” zakresu, na przykład:
Również BOOST_FOREACH używa go pod maską. Aby to zrealizować, jest to możliwe nie tylko w if, ale także w przełączniku:
i za chwilę pętla:
(a także w stanie). Ale nie jestem pewien, czy te wszystkie są przydatne :)
źródło
if((a = f()) == b) ...
, ale ta odpowiedź w rzeczywistości deklaruje zmienną w warunku.for(...; int i = foo(); ) ...;
To przejdzie przez ciało, o ilei
jest prawdziwe, inicjując je za każdym razem. Pętla, którą pokazujesz, po prostu demonstruje deklarację zmiennej, ale nie deklarację zmiennej, która jednocześnie działa jako warunek :)Zapobieganie operatorowi przecinka wywoływania przeciążeń operatora
Czasami używasz operatora przecinka, ale chcesz się upewnić, że żaden operator przecinka zdefiniowany przez użytkownika nie przeszkadza, ponieważ na przykład polegasz na punktach sekwencji między lewą a prawą stroną lub chcesz się upewnić, że nic nie koliduje z pożądanym akcja. Tutaj
void()
do gry wkracza:Zignoruj miejsca, które ustawiłem dla warunku i kodu. Ważny jest
void()
, co zmusza kompilator do używania wbudowanego operatora przecinka. Może to być przydatne także przy implementowaniu klas cech.źródło
Inicjalizacja tablicy w konstruktorze. Na przykład w klasie, jeśli mamy tablicę
int
as:Możemy zainicjować wszystkie elementy tablicy do wartości domyślnych (tutaj wszystkie elementy tablicy na zero) w konstruktorze jako:
źródło
Oooh, zamiast tego mogę wymyślić listę nienawiści do zwierząt:
Na plus
źródło
Możesz uzyskać dostęp do chronionych danych i elementów składowych funkcji dowolnej klasy, bez niezdefiniowanego zachowania iz oczekiwaną semantyką. Czytaj dalej, aby dowiedzieć się, jak to zrobić. Przeczytaj również raport wady na ten temat.
Zwykle C ++ zabrania dostępu do niestatycznie chronionych elementów składowych obiektu klasy, nawet jeśli ta klasa jest twoją klasą bazową
To zabronione: Ty i kompilator nie wiecie, na co właściwie wskazuje odniesienie. Może to być
C
obiekt, w którym to przypadku klasaB
nie ma żadnego interesu i nie ma pojęcia o swoich danych. Taki dostęp jest udzielany tylko wtedy, gdyx
jest odwołaniem do klasy pochodnej lub klasy pochodnej. I może pozwolić dowolnemu fragmentowi kodu na odczytanie dowolnego chronionego elementu członkowskiego, po prostu tworząc klasę „do wyrzucenia”, która odczytuje elementy, na przykładstd::stack
:Z pewnością, jak widzisz, spowodowałoby to zbyt duże szkody. Ale teraz wskaźniki dla członków pozwalają na obejście tej ochrony! Kluczową kwestią jest to, że typ wskaźnika elementu członkowskiego jest powiązany z klasą, która faktycznie zawiera wspomniany element członkowski, a nie z klasą określoną podczas pobierania adresu. To pozwala nam ominąć sprawdzanie
I oczywiście działa to również na
std::stack
przykładzie.Będzie to jeszcze łatwiejsze dzięki deklaracji using w klasie pochodnej, która sprawia, że nazwa elementu członkowskiego jest publiczna i odwołuje się do elementu członkowskiego klasy bazowej.
źródło
Inną ukrytą funkcją jest możliwość wywoływania obiektów klas, które można konwertować na wskaźniki funkcji lub odwołania. Rozpoznanie przeciążenia jest wykonywane na ich wyniku, a argumenty są doskonale przekazywane.
Są to nazywane „zastępcze funkcje wywoławcze”.
źródło
Ukryte funkcje:
Jeśli funkcja zgłasza wyjątek niewymieniony w specyfikacjach wyjątków, ale funkcja ma
std::bad_exception
w specyfikacji wyjątku, wyjątek jest konwertowany nastd::bad_exception
i generowany automatycznie. W ten sposób będziesz przynajmniej wiedział, żebad_exception
został rzucony. Przeczytaj więcej tutaj .funkcja try bloków
Słowo kluczowe template w ujednoznacznianiu typów definicji w szablonie klasy. Jeśli nazwa specjalizacji szablonu członkiem pojawia po
.
,->
lub::
operatora, a nazwa ta ma wyraźnie wykwalifikowanych parametrów szablonu, poprzedź nazwę użytkownika szablonu z szablonu słów kluczowych. Przeczytaj więcej tutaj .wartości domyślne parametrów funkcji można zmienić w czasie wykonywania. Przeczytaj więcej tutaj .
A[i]
działa tak dobrze, jaki[A]
Tymczasowe instancje klasy można modyfikować! Funkcję składową inną niż stała można wywołać na obiekcie tymczasowym. Na przykład:
Przeczytaj więcej tutaj .
Jeśli dwa różne typy występują przed i po wyrażeniu operatora
:
ternary (?:
), to wynikowy typ wyrażenia jest tym, który jest najbardziej ogólnym z nich. Na przykład:źródło
map::operator[]
tworzy wpis, jeśli brakuje klucza i zwraca odwołanie do domyślnej wartości wpisu. Możesz więc napisać:Jestem zdumiony, ilu programistów C ++ o tym nie wie.
źródło
.find()
.const map::operator[]
generuje komunikaty o błędach”Umieszczanie funkcji lub zmiennych w bezimiennej przestrzeni nazw unieważnia użycie w
static
celu ograniczenia ich do zakresu plików.źródło
static
w zakresie globalnym nie jest w żaden sposób przestarzały. (Dla porównania: C ++ 03 §D.2)static
użycie powinno być używane tylko w ramach typu klasy lub funkcji.Definiowanie zwykłych funkcji znajomych w szablonach klas wymaga szczególnej uwagi:
W tym przykładzie dwie różne instancje tworzą dwie identyczne definicje - co jest bezpośrednim naruszeniem ODR
Dlatego musimy upewnić się, że parametry szablonu szablonu klasy pojawiają się w typie dowolnej funkcji zaprzyjaźnionej zdefiniowanej w tym szablonie (chyba że chcemy zapobiec więcej niż jednej instancji szablonu klasy w określonym pliku, ale jest to raczej mało prawdopodobne). Zastosujmy to do odmiany naszego poprzedniego przykładu:
Zastrzeżenie: wkleiłem tę sekcję z C ++ Templates: The Complete Guide / Section 8.4
źródło
Funkcje void mogą zwracać wartości void
Mało znane, ale poniższy kod jest w porządku
Jak również ten dziwnie wyglądający
Wiedząc o tym, możesz skorzystać w niektórych obszarach. Jeden przykład:
void
funkcje nie mogą zwracać wartości, ale możesz też nie zwracać niczego, ponieważ mogą być tworzone z wartością non-void. Zamiast przechowywać wartość w zmiennej lokalnej, co spowoduje błąd dlavoid
, po prostu zwróć wartość bezpośrednioźródło
Wczytaj plik do wektora ciągów:
istream_iterator
źródło
vector<string> V((istream_iterator<string>(cin)), istream_iterator<string>());
- brak nawiasów po drugim parametrzeMożesz tworzyć szablony pól bitowych.
Nie wymyśliłem jeszcze żadnego celu, ale na pewno mnie to zaskoczyło.
źródło
Jedna z najciekawszych gramatyk ze wszystkich języków programowania.
Trzy z tych rzeczy należą do siebie, a dwie są czymś zupełnie innym ...
Wszystkie oprócz trzeciego i piątego definiują
SomeType
obiekt na stosie i inicjalizują go (zu
w pierwszych dwóch przypadkach i domyślnym konstruktorem w czwartym. Trzeci to deklaracja funkcji, która nie przyjmuje parametrów i zwraca aSomeType
. Piąty jest podobnie deklarowany funkcja, która przyjmuje jeden parametr według wartości typuSomeType
o nazwieu
.źródło
Pozbycie się deklaracji forward:
Pisanie instrukcji przełączających z?: Operatorami:
Robi wszystko w jednej linii:
Zerowanie struktur bez memsetu:
Normalizowanie / owijanie wartości kąta i czasu:
Przypisywanie referencji:
źródło
FStruct s = {};
jest jeszcze krótsza.main
? Sugerujęglobal().main();
i po prostu zapomnieć o Singleton ( można po prostu praca z tymczasowej, która dostaje to żywotność rozszerzony )Trójskładnikowy operator warunkowy
?:
wymaga , aby jego drugi i trzeci operand miały „zgodne” typy (mówiąc nieformalnie). Ale to wymaganie ma jeden wyjątek (gra słów zamierzona): albo drugi, albo trzeci operand może być wyrażeniem rzucającym (który ma typvoid
), niezależnie od typu drugiego operandu.Innymi słowy, za pomocą
?:
operatora można napisać następujące, poprawnie poprawne wyrażenia C ++Przy okazji, fakt, że wyrażenie throw jest w rzeczywistości wyrażeniem (typu
void
), a nie instrukcją, jest kolejną mało znaną cechą języka C ++. Oznacza to między innymi, że poniższy kod jest całkowicie poprawnychociaż nie ma sensu robić tego w ten sposób (może w jakimś ogólnym kodzie szablonu może się to przydać).
źródło
Zasada dominacji jest przydatna, ale mało znana. Mówi się, że nawet jeśli w nieunikalnej ścieżce przez kratkę klasy bazowej, wyszukiwanie nazw dla częściowo ukrytego elementu członkowskiego jest unikalne, jeśli element członkowski należy do wirtualnej klasy bazowej:
Użyłem tego do zaimplementowania obsługi wyrównania, która automatycznie określa najściślejsze dopasowanie za pomocą reguły dominacji.
Dotyczy to nie tylko funkcji wirtualnych, ale także nazw typedef, elementów statycznych / niewirtualnych i czegokolwiek innego. Widziałem, że jest używany do implementowania nadpisywalnych cech w metaprogramach.
źródło
struct C
w swoim przykładzie ...? Twoje zdrowie.