W zależności od tego, na jakim etapie jesteś w nauce języków programowania (a konkretnie C++), LearnCpp.com może być jedynym źródłem, którego używasz do nauki C++ lub coś sprawdzić. LearnCpp.com ma na celu wyjaśnianie pojęć w sposób przyjazny dla początkujących, ale po prostu nie może omówić wszystkich aspektów języka. Gdy zaczniesz zgłębiać tematy wykraczające poza tematy omówione w tych samouczkach, nieuchronnie natkniesz się na pytania, na które te samouczki nie dają odpowiedzi. W takim przypadku będziesz musiał skorzystać z zasobów zewnętrznych.
Jednym z takich zasobów jest Stack Overflow, w którym możesz zadawać pytania (lub lepiej, przeczytać odpowiedź na to samo pytanie, które ktoś wcześniej zadał). Czasem jednak lepszym pierwszym przystankiem jest przewodnik informacyjny. W przeciwieństwie do tutoriali, które skupiają się na najważniejszych tematach i używają nieformalnego/wspólnego języka, aby ułatwić naukę, podręczniki opisują C++ precyzyjnie, używając formalnej terminologii. Z tego powodu materiały referencyjne są zwykle wyczerpujące, dokładne i… trudne do zrozumienia.
W tej lekcji pokażemy, jak używać cppreference, popularnego standardowego źródła, do którego odwołujemy się podczas lekcji, poprzez zapoznanie się z 3 przykładami.
Przegląd
Cppreference wita Cię przeglądem Podstawowy język i biblioteki:

Stąd możesz dostać się do wszystkiego, co cppreference ma do zaoferowania, ale łatwiej jest skorzystać z funkcji wyszukiwania lub wyszukiwarki. Przegląd to świetne miejsce do odwiedzenia po ukończeniu samouczków na LearnCpp.com, aby zagłębić się w biblioteki i zobaczyć, co jeszcze język ma do zaoferowania, o czym możesz nie wiedzieć.
Górna połowa tabeli pokazuje funkcje aktualnie dostępne w języku, podczas gdy dolna połowa pokazuje specyfikacje techniczne, czyli funkcje, które mogą, ale nie muszą zostać dodane do C++ w przyszłej wersji, lub które zostały już częściowo zaakceptowane w tym języku. Może to być przydatne, jeśli chcesz zobaczyć, jakie nowe możliwości zostaną wkrótce wprowadzone.
Począwszy od C++ 11, cppreference oznacza wszystkie funkcje standardową wersją językową, w której zostały dodane. Wersja standardowa to mała zielona liczba, którą możesz zobaczyć obok niektórych łączy na powyższym obrazku. Funkcje bez numeru wersji są dostępne od C++ 98/03. Numery wersji znajdują się nie tylko w przeglądzie, ale wszędzie w cpppreference, informując dokładnie, czego można, a czego nie można użyć w konkretnej wersji C++.
Ostrzeżenie
Jeśli korzystasz z wyszukiwarki, a specyfikacja techniczna została właśnie przyjęta do standardu, możesz zostać przekierowany do specyfikacji technicznej, a nie do oficjalnego odniesienia, które może się różnić.
Wskazówka
Cppreference jest odniesieniem zarówno dla C++, jak i C. Ponieważ C++ ma takie same nazwy funkcji jak C, możesz się znaleźć w referencji C po wyszukaniu czegoś. Adres URL i pasek nawigacyjny na górze cppreference zawsze pokazują, czy przeglądasz odwołanie do C lub C++.
std::string::length
Zaczniemy od sprawdzenia funkcji, którą znasz z poprzedniej lekcji, std::string::length, która zwraca długość łańcucha.
W prawym górnym rogu cppreference wyszukaj „string”. Spowoduje to wyświetlenie długiej listy typów i funkcji, z których w tej chwili istotna jest tylko górna część.

Mogliśmy od razu wyszukać „długość łańcucha”, ale aby pokazać jak najwięcej w tej lekcji, wybierzemy dłuższą drogę. Kliknięcie „Biblioteka ciągów” przenosi nas do strony opisującej różne rodzaje ciągów znaków obsługiwanych przez C++.

Jeśli zajrzymy do sekcji „std::basic_string”, zobaczymy listę typedefs, a na tej liście znajduje się std::string.
Kliknięcie „std::string” prowadzi do strony dla std::basic_string. Nie ma strony dla std::string, ponieważ std::string jest typedef for std::basic_string<char>, co ponownie można zobaczyć na liście typedef :

Klasa <char> oznacza, że każdy znak ciągu jest typu char. Zauważysz, że C++ oferuje inne ciągi znaków, które używają różnych typów znaków. Mogą one być przydatne, gdy używasz Unicode zamiast ASCII.
W dalszej części tej samej strony znajduje się lista funkcji składowych (zachowań charakterystycznych dla typu). Jeśli chcesz wiedzieć, co możesz zrobić z typem, ta lista jest bardzo wygodna. Na tej liście znajdziesz wiersz dla length (oraz size).
Podążanie za linkiem prowadzi nas do szczegółowego opisu funkcji length i size, które robią to samo.
Góra każdej strony zaczyna się od krótkiego podsumowania funkcji i składni, przeciążeń lub deklaracji:

Tytuł strony pokazuje nazwę klasy i funkcji ze wszystkimi parametrami szablonu. Tę część możemy pominąć. Poniżej tytułu widzimy wszystkie różne przeciążenia funkcji (różne wersje funkcji o tej samej nazwie) i standard językowy, do którego się odnoszą.
Poniżej możemy zobaczyć parametry pobierane przez funkcję i znaczenie zwracanej wartości.
Ponieważ std::string::length to prosta funkcja, na tej stronie nie ma zbyt wiele treści. Wiele stron pokazuje przykładowe zastosowania dokumentowanej przez nich funkcji, podobnie jak ta:

Gdy będziesz jeszcze uczyć się C++, w przykładach pojawią się funkcje, których nie widziałeś wcześniej. Jeśli jest wystarczająco dużo przykładów, prawdopodobnie jesteś w stanie zrozumieć ich wystarczającą ilość, aby mieć pojęcie o tym, jak używana jest dana funkcja i co robi. Jeśli przykład jest zbyt skomplikowany, możesz poszukać przykładu gdzie indziej lub przeczytać odniesienia do części, których nie rozumiesz (możesz kliknąć funkcje i typy w przykładach, aby zobaczyć, co robią).
Teraz wiemy, co std::string::length robi, ale wiedzieliśmy to wcześniej. Rzućmy okiem na coś nowego!
std::cin.ignore
W lekcji 9.5 — std::cin i obsługa nieprawidłowych danych wejściowych, o którym mówiliśmy std::cin.ignore, który służy do ignorowania wszystkiego aż do końca wiersza. Jednym z parametrów tej funkcji jest długa i pełna wartość. Co to było znowu? Nie możesz po prostu użyć dużej liczby? Co w ogóle daje ten argument? Rozwiążmy to!
Wpisanie „std::cin.ignore” w wyszukiwaniu cppreference daje następujące wyniki:

std::cin, std::wcin- Chcemy.ignore, a nie zwykłystd::cin.std::basic_istream<CharT,Traits>::ignore- Ej, co to jest? Pomińmy na razie.std::ignore- Nie, to nie to.std::basic_istream- To też nie to.
Nie ma tego, co teraz? Przejdźmy do std::cin i stamtąd ruszajmy dalej. Na tej stronie nie ma nic od razu oczywistego. Na górze możemy zobaczyć deklarację std::cin i std::wcin, która mówi nam, który nagłówek musimy dołączyć, aby użyć std::cin:

Widzimy, że std::cin jest obiektem typu std::istream. Przejdźmy do linku do std::istream:

Trzymaj się! Widzieliśmy to std::basic_istream wcześniej, gdy szukaliśmy „std::cin.ignore” w naszej wyszukiwarce. Okazuje się, że istream jest nazwą typedef dla basic_istream, więc może jednak nasze wyszukiwanie nie było takie złe.
Przewijając tę stronę, witają nas znajome funkcje:

Użyliśmy już wielu z tych funkcji: operator>>, get, getline, ignore. Przewiń tę stronę, aby dowiedzieć się, co jeszcze znajduje się w std::cin. Następnie kliknij ignore, bo to nas interesuje.

Na górze strony znajduje się sygnatura funkcji oraz opis działania funkcji i jej dwóch parametrów. Znaki = po parametrach wskazują a argument domyślny (omówiliśmy to w lekcji 11.5 -- Domyślne argumenty). Jeśli nie podamy argumentu dla parametru, który ma wartość domyślną, zostanie użyta wartość domyślna.
Pierwszy punktor odpowiada na wszystkie nasze pytania. Widzimy, że std::numeric_limits<std::streamsize>::max() ma specjalne znaczenie dla std::cin.ignore, ponieważ wyłącza sprawdzanie liczby znaków. Oznacza to std::cin.ignore będzie ignorował znaki, dopóki nie znajdzie separatora lub nie zabraknie znaków do sprawdzenia.
W wielu przypadkach nie musisz czytać całego opisu funkcji, jeśli już go znasz, ale zapomniałeś, co oznaczają parametry lub zwracana wartość. W takich sytuacjach wystarczy przeczytać opis parametru lub wartości zwracanej.

Opis parametru jest krótki. Nie zawiera specjalnej obsługi std::numeric_limits<std::streamsize>::max() ani innych warunków zatrzymania, ale służy jako dobre przypomnienie.
Przykład gramatyki języka
Oprócz biblioteki standardowej, cppreference dokumentuje również gramatykę języka. Oto poprawny program:
#include <iostream>
int getUserInput()
{
int i{};
std::cin >> i;
return i;
}
int main()
{
std::cout << "How many bananas did you eat today? \n";
if (int iBananasEaten{ getUserInput() }; iBananasEaten <= 2)
{
std::cout << "Yummy\n";
}
else
{
std::cout << iBananasEaten << " is a lot!\n";
}
return 0;
}Dlaczego w warunku if-statement znajduje się definicja zmiennej? Użyjmy cppreference, aby dowiedzieć się, co robi, wyszukując „wyrażenie cppreference if” w naszej ulubionej wyszukiwarce. Takie postępowanie prowadzi nas do instrukcje if. Na górze znajduje się opis składni.

Przyjrzyj się składni if-statement. Jeśli usuniesz wszystkie opcjonalne części, otrzymasz if-statement który już znasz. Przed condition znajduje się opcjonalny init-statement, który wygląda tak, jak w powyższym kodzie.
if ( init-statement condition ) statement-true if ( init-statement condition ) statement-true else statement-false
Poniżej opisu składni znajduje się wyjaśnienie każdej części składni, w tym init-statement. Mówi, że init-statement jest zazwyczaj deklaracją zmiennej z inicjatorem.
Po składni znajduje się wyjaśnienie if-statements i proste przykłady:

Wiemy już jak działa if-statements , a przykłady nie zawierają init-statement, więc przewijamy trochę w dół, aby znaleźć sekcję poświęconą do if-statements za pomocą inicjatorów:

Najpierw pokazano, jak można zapisać init-statement bez faktycznego użycia init-statement. Teraz wiemy, co robi dany kod. Jest to zwykła deklaracja zmiennej, po prostu włączona do if-statement.
Następne zdanie jest interesujące, ponieważ pozwala nam wiedzieć, że nazwy z init-statement są dostępne w oba oświadczenia (statement-true i statement-false). Może to być zaskakujące, ponieważ w przeciwnym razie można by założyć, że zmienna jest dostępna tylko w statement-true.
Klasa init-statement przykładach użycia funkcji i typów, których jeszcze nie omówiliśmy. Nie musisz rozumieć wszystkiego, co widzisz, aby zrozumieć, jak działa init-statement . Pomińmy wszystko, co jest zbyt zagmatwane, dopóki nie znajdziemy czegoś, z czym możemy pracować:
// Iterators, we don't know them. Skip.
if (auto it = m.find(10); it != m.end()) { return it->second.size(); }
// [10], what's that? Skip.
if (char buf[10]; std::fgets(buf, 10, stdin)) { m[0] += buf; }
// std::lock_guard, we don't know that, but it's some type. We know what types are!
if (std::lock_guard lock(mx); shared_flag) { unsafe_ping(); shared_flag = false; }
// This is easy, that's an int!
if (int s; int count = ReadBytesWithSignal(&s)) { publish(count); raise(s); }
// Whew, no thanks!
if (auto keywords = {"if", "for", "while"};
std::any_of(keywords.begin(), keywords.end(),
[&s](const char* kw) { return s == kw; })) {
std::cerr << "Token must not be a keyword\n";
}Najprostszym przykładem wydaje się być ten z int. Następnie zwracamy uwagę na średnik i pojawia się inna definicja, dziwna… Wróćmy do std::lock_guard przykładu.
if (std::lock_guard lock(mx); shared_flag)
{
unsafe_ping();
shared_flag = false;
}Na podstawie tego stosunkowo łatwo jest zobaczyć, jak działa init-statement . Zdefiniuj zmienną (lock), następnie średnik i warunek. Dokładnie tak się stało w naszym przykładzie.
Ostrzeżenie dotyczące dokładności cppreference
Cppreference nie jest oficjalnym źródłem dokumentacji — jest to raczej wiki. Dzięki wiki każdy może dodawać i modyfikować treść — treść pochodzi od społeczności. Chociaż oznacza to, że ktoś może łatwo dodać błędne informacje, dezinformacja jest zazwyczaj szybko wychwytywana i usuwana, co sprawia, że cppreference jest wiarygodnym źródłem.
Jedynym oficjalnym źródłem C++ jest standard (bezpłatne wersje robocze na github), który jest dokumentem formalnym, którego nie można łatwo wykorzystać jako odniesienie.
Czas quizu
Pytanie nr 1
Co wypisze poniższy program? Nie uruchamiaj go, użyj odniesienia, aby dowiedzieć się, co erase robi.
#include <iostream>
#include <string>
int main()
{
std::string str{ "The rice is cooking" };
str.erase(4, 11);
std::cout << str << '\n';
return 0;
}Wskazówka
Gdy znajdziesz erase w cppreference, możesz zignorować przeciążenia używające iteratorów.
Wskazówka
Indeksy w C++ zaczynają się od 0. Znak pod indeksem 0 w ciągu „House” to „H”, przy 1 to „o” i tak on.
Pytanie nr 2
W poniższym kodzie zmodyfikuj str tak, aby jego wartość brzmiała „Wczoraj widziałem niebieski samochód”. bez powtarzania ciągu. Na przykład nie rób tego:
str = "I saw a blue car yesterday.";Wystarczy wywołać tylko jedną funkcję, aby zamienić „czerwony” na „niebieski”.
#include <iostream>
#include <string>
int main()
{
std::string str{ "I saw a red car yesterday." };
// ...
std::cout << str << '\n'; // I saw a blue car yesterday.
return 0;
}
