---------------
char c = 'a';
char*p = &c; // p zawiera adres c; & jest operatorem adresowania
---------------
char c = 'a';
char*p = &c; // p zawiera adres c; & jest operatorem adresowania
char c2 =*p; // c2 == 'a'; * jest operatorem dereferencji
---------------
int*pi;           // wskanik do int
char**ppc;        // wskanik do wskanika do char
int*ap[15];       // tablica 15 wskanikw do int
int (*fp)(char*); // wskanik do funkcji pobierajcej argument char*; zwraca int
int*f(char*);     // funkcja przyjmujca argument char*; zwraca wskanik do int
---------------
void f(int*pi)
{
    void*pv = pi; // OK: niejawna konwersja int* na void*
    *pv;          // bd: nie mona wyuska void*
    ++pv;         // bd: nie mona zwikszy void* (rozmiar wskazywanego obiektu jest nieznany)

    int*pi2 = static_cast<int*>(pv);       // jawna konwersja z powrotem na int*

    double*pd1 = pv;                       // bd
    double*pd2 = pi;                       // bd
    double*pd3 = static_cast<double*>(pv); // niebezpieczne (11.5.2)
}
---------------
void* my_alloc(size_t n); // alokacja n bajtw z mojej specjalnej sterty
---------------
int*pi = nullptr;
double*pd = nullptr;
int i = nullptr; // bd: i nie jest wskanikiem
---------------
int* x = 0; // x ma warto nullptr
---------------
int* p = NULL; // uycie makra NULL
---------------
int* p = NULL; // bd: nie mona przypisa void* do int*
---------------
float v[3]; // tablica trzech liczb zmiennoprzecinkowych: v[0], v[1], v[2]
char*a[32]; // tablica 32 wskanikw na char: a[0] .. a[31]
---------------
void f()
{
    int aa[10];
    aa[6] = 9;      // przypisanie do sidmego elementu aa
    int x = aa[99]; // niezdefiniowane dziaanie
}
---------------
void f(int n)
{
    int v1[n];         // bd: rozmiar tablicy nie jest wyraeniem staym
    vector<int> v2(n); // OK: wektor zawierajcy n elementw typu int
}
---------------
int a1[10];              // 10 liczb typu int w pamici statycznej

void f()
{
    int a2 [20];         // 20 liczb typu int na stosie
    int*p = new int[40]; // 40 liczb typu int w pamici wolnej
    //...
}
---------------
int v1[] = { 1, 2, 3, 4 };
char v2[] = { 'a', 'b', 'c', 0 }
---------------
char v3[2] = { 'a', 'b', 0 }; // bd: za duo inicjatorw
char v4[3] = { 'a', 'b', 0 }; // OK
---------------
int v5[8] = { 1, 2, 3, 4 };
---------------
int v5[] = { 1, 2, 3, 4 , 0, 0, 0, 0 };
---------------
int v6[8] = v5; // bd: nie mona skopiowa tablicy (nie mona przypisa int* do tablicy)
v6 = v5;        // bd: nie mona przypisywa do tablicy
---------------
"to jest acuch"
---------------
siz eof("Bohr")==5
---------------
void f()
{
    char* p = "Plato"; // bd, ale w standardach starszych od C++11 jest to akceptowalne
    p[4] = 'e';        // bd: przypisanie do const
}
---------------
void f()
{
    char p[] = "Zeno"; // p jest tablic piciu znakw
    p[0] = 'R';        // OK
}
---------------
const char* error_message(int i)
{
    // ...
    return "bd zakresu";
}
---------------
const char* p = "Heraclitus";
const char* q = "Heraclitus";

void g()
{
    if (p == q) cout << "jedna!\n"; // wynik jest zaleny od implementacji
    // ...
}
---------------
cout<<"Odtwrz dwik na zakoczenie\a\n";
---------------
"to nie jest acuch,
tylko bd skadni"
---------------
char alpha[] = "abcdefghijklmnopqrstuvwxyz"
               "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
---------------
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
---------------
string s = "\\w\\\\w"; // mam nadziej, e nie zrobiem bdu
---------------
string s = R"(\w\\w)"; // jestem pewny, e tu nie ma bdu
---------------
R"("acuch w cudzysowie podwjnym")" // tutaj acuch to "acuch w cudzysowie podwjnym"
---------------
R"***("acuch w podwjnym cudzysowie zawierajcy typowy ogranicznik ("))")***"
// "acuch w podwjnym cudzysowie zawierajcy typowy ogranicznik ("))"
---------------
"('(?:[^\\\\']|\\\\.)*'|\"(?:[^\\\\\"]|\\\\.)*\")|" // czy te pi ukonikw zostao uytych poprawnie, czy nie?
---------------
string counts {R"(1
22
333)"};
---------------
string x {"1\n22\n333"};
---------------
"folder\\plik"     // acuch znakw z zestawu domylnego implementacji
R"(folder\plik)"   // surowy acuch znakw z zestawu domylnego implementacji
u8"folder\\plik"   // acuch UTF-8
u8R"(folder\plik)" // surowy acuch UTF-8
u"folder\\plik"    // acuch UTF-16
uR"(folder\plik)"  // surowy acuch UTF-16
U"folder\\plik"    // acuch UTF-32
UR"(folder\plik)"  // surowy acuch UTF-32
---------------
u8"Oficjalne samogoski w alfabecie duskim to: a, e, i, o, u, \u00E6, \u00F8, \u00E5 oraz y."
---------------
Oficjalne samogoski w alfabecie duskim to: a, e, i, o, u, a, o, a oraz y.
---------------
int v[] = { 1, 2, 3, 4 };
int* p1 = v;     // wskanik do pierwszego elementu (niejawna konwersja)
int* p2 = &v[0]; // wskanik do pierwszego elementu
int* p3 = v+4;   // wskanik do miejsca za ostatnim elementem
---------------
int* p4 = v-1; // przed pocztkiem wynik jest niezdefiniowany: nie rb tego
int* p5 = v+7; // za kocem wynik jest niezdefiniowany: nie rb tego
---------------
extern "C" int strlen(const char*); // z <string.h>

void f()
{
    char v[] = "Annemarie";
    char* p=v; // niejawna konwersja char[] na char*
    strlen(p);
    strlen(v); // niejawna konwersja char[] na char*
    v=p;       // bd: nie mona przypisa do tablicy
}
---------------
void fi(char v[])
{
    for (int i = 0; v[i]!=0; ++i)
    use(v[i]);
}

void fp(char v[])
{
    for (char* p=v;*p!=0; ++p)
    use(*p);
}
---------------
a[j] ==*(&a[0]+j) ==*(a+j) ==*(j+a) == j[a]
---------------
template<typename T>
int byte_diff(T*p, T*q)
{
    return reinterpret_cast<char*>(q)-reinterpret_cast<char*>(p);
}

void diff_test()
{
    int vi[10];
    short vs[10];
    cout << vi << ' ' << &vi[1] << ' ' << &vi[1]-&vi[0] << ' ' << byte_diff(&vi[0],&vi[1]) << '\n';
    cout << vs << ' ' << &vs[1] << ' ' << &vs[1]-&vs[0] << ' ' << byte_diff(&vs[0],&vs[1]) << '\n';
}
---------------
0x7fffaef0 0x7fffaef4 1 4
0x7fffaedc 0x7fffaede 1 2
---------------
void f()
{
    int v1[10];
    int v2[10];

    int i1 = &v1[5]-&v1[3]; // i1 = 2
    int i2 = &v1[5]-&v2[3]; // wynik niezdefiniowany

    int*p1 = v2+2;          // p1 = &v2[2]
    int*p2 = v2-2;          // *p2 niezdefiniowany
}
---------------
void fp(char v[], int size)
{
    for (int i=0; i!=size; ++i)
        use(v[i]); // mamy nadziej, e v zawiera przynajmniej size elementw
    for (int x : v)
        use(x);    // bd: zakresowa ptla for nie dziaa dla wskanikw

    const int N = 7;
    char v2[N];
    for (int i=0; i!=N; ++i)
        use(v2[i]);
    for (int x : v2)
        use(x);    // zakresowa ptla for dziaa dla tablic o nieznanym rozmiarze
}
---------------
int ma[3][5]; // trzy tablice po pi liczb typu int
---------------
void init_ma()
{
    for (int i = 0; i!=3; i++)
        for (int j = 0; j!=5; j++)
            ma[i][j] = 10*i+j;
}
---------------
void print_ma()
{
    for (int i = 0; i!=3; i++) {
        for (int j = 0; j!=5; j++)
            cout << ma[i][j] << '\t';
        cout << '\n';
    }
}
---------------
int bad[3,5];         // bd: w wyraeniach staych nie mona uywa przecinka
int good[3][5];       // trzy tablice po pi liczb typu int
int ouch = good[1,4]; // bd: liczba typu int zainicjowana przez int* (good[1,4] oznacza good[4], ktry jest typu int*)
int nice = good[1][4];
---------------
void comp(double arg[10]) // arg jest typu double*
{
    for (int i=0; i!=10; ++i)
        arg[i]+=99;
}

void f()
{
    double a1[10];
    double a2[5];
    double a3[100];

    comp(a1);
    comp(a2); // katastrofa!
    comp(a3); // uywa tylko 10 pierwszych elementw
};
---------------
void comp(double*arg)
{
    for (int i=0; i!=10; ++i)
        arg[i]+=99;
}
---------------
void print_m35(int m[3][5])
{
    for (int i = 0; i!=3; i++) {
        for (int j = 0; j!=5; j++)
            cout << m[i][j] << '\t';
        cout << '\n';
    }
}
---------------
void print_mi5(int m[][5], int dim1)
{
    for (int i = 0; i!=dim1; i++) {
        for (int j = 0; j!=5; j++)
            cout << m[i][j] << '\t';
        cout << '\n';
    }
}
---------------
void print_mij(int m[][], int dim1, int dim2) // nie dziaa tak, jak oczekiwaaby wikszo osb
{
    for (int i = 0; i!=dim1; i++) {
        for (int j = 0; j!=dim2; j++)
            cout << m[i][j] << '\t'; // niespodzianka!
        cout << '\n';
    }
}
---------------
void print_mij(int*m, int dim1, int dim2)
{
    for (int i = 0; i!=dim1; i++) {
        for (int j = 0; j!=dim2; j++)
            cout << m[i*dim2+j] << '\t'; // niejasne
        cout << '\n';
    }
}
---------------
int test()
{
    int v[3][5] = {
        {0,1,2,3,4}, {10,11,12,13,14}, {20,21,22,23,24}
    };

    print_m35(v);
    print_mi5(v,3);
    print_mij(&v[0][0],3,5);
}
---------------
const int model = 90;           // model jest const
const int v[] = { 1, 2, 3, 4 }; // v[i] jest const
const int x;                    // bd: brak inicjatora
---------------
void f()
{
    model = 200; // bd
    v[2] = 3;    // bd
}
---------------
void g(const X*p)
{
    // tu nie mona zmodyfikowa *p
}
---------------
void f1(char*p)
{
    char s[] = "Gorm";

    const char*pc = s;        // wskanik do staej
    pc[3] = 'g';              // bd: pc wskazuje sta
    pc = p;                   // OK

    char*const cp = s;        // stay wskanik
    cp[3] = 'a';              // OK
    cp = p;                   // bd: cp jest sta

    const char*const cpc = s; // stay wskanik do const
    cpc[3] = 'a';             // bd: cpc wskazuje sta
    cpc = p;                  // bd: cpc jest sta
}
---------------
char *const cp;  // stay wskanik do char
char const* pc;  // wskanik do const char
const char* pc2; // wskanik do const char
---------------
const char*strchr(const char*p, char c); // znajduje pierwsze wystpienie c w p
char*strchr(char*p, char c);             // znajduje pierwsze wystpienie c w p
---------------
void f4()
{
    int a = 1;
    const int c = 2;
    const int*p1 = &c; // OK
    const int*p2 = &a; // OK
    int*p3 = &c;       // bd: inicjacja int* przy uyciu const int*
    *p3 = 7;           // prba zmiany wartoci c
}
---------------
void confused(int*p)
{
    // usun p?
}

int global {7};

void f()
{
    X*pn = new int{7};
    int i {7};
    int q = &i;
    confused(pn);
    confused(q);
    confused(&global);
}
---------------
template<class T>
class vector {
    T*elem;
    // ...
public:
    T& operator[](int i) { return elem[i]; }             // zwraca referencj do elementu
    const T& operator[](int i) const { return elem[i]; } // zwraca referencj do elementu const

    void push_back(const T& a);                          // przekazuje element do dodania przez referencj
    // ...
};

void f(const vector<double>& v)
{
    double d1 = v[1]; // kopiuje warto double, do ktrej odnosi si v.operator[](1), do d1
    v[2] = 7;         // umieszcza 7 w elemencie double, do ktrego odnosi si wynik wyraenia v.operator[](2)

    v.push_back(d1);  // przekazuje funkcji push_back() referencj do d1
}
---------------
void f()
{
    int var = 1;
    int& r {var}; // r i var teraz odnosz si do tej samej liczby typu int
    int x = r;    // x ma warto 1
    r=2;          // var ma warto 2
}
---------------
int var = 1;
int& r1 {var};   // OK: r1 zainicjowana
int& r2;         // bd: brak inicjatora
extern int& r3;  // OK: r3 zainicjowano gdzie indziej
---------------
void g()
{
    int var = 0;
    int& rr {var};
    ++rr;         // var zwiksza si do 1
    int*pp = &rr; // pp wskazuje var
}
---------------
double& dr = 1;           // bd: musi by warto lewostronna
const double& cdr {1};    // OK
---------------
double temp = double{1};  // utwrz tymczasow zmienn z odpowiedni wartoci
const double& cdr {temp}; // nastpnie uyj tej zmiennej jako inicjatora cdr
---------------
void increment(int& aa)
{
    ++aa;
}

void f()
{
    int x = 1;
    increment(x); // x=2
}
---------------
int next(int p) { return p+1; }

void g()
{
    int x = 1;
    increment(x); // x=2
    x = next(x);  // x=3
}
---------------
template<class K, class V>
class Map { // prosta klasa mapy
public:
    V& operator[](const K& v); // zwraca warto dla klucza v

    pair<K,V>*begin() { return &elem[0]; }
    pair<K,V>*end() { return &elem[0]+elem.size(); }
private:
    vector<pair<K,V>> elem;   // pary {klucz,warto}
};
---------------
template<class K, class V>
V& Map<K,V>::operator[](const K& k)
{
    for (auto& x : elem)
        if (k == x.first)
            return x.second;

    elem.push_back({k,V{}});   // dodaje par na kocu (4.4.2)
    return elem.back().second; // zwraca (domyln) warto nowego elementu
}
---------------
int main() // liczy, ile jest wystpie kadego sowa na wejciu
{
    Map<string,int> buf;
    for (string s; cin>>s;) ++buf[s];

    for (const auto& x : buf)
        cout << x.first << ": " << x.second << '\n';
}
---------------
aa bb bb aa aa bb aa aa
---------------
aa: 5
bb: 3
---------------
string var {"Cambridge"};
string f();
string& r1 {var};              // referencja lewostronna, wizanie r1 z var (wartoci lewostronn)
string& r2 {f()};              // referencja lewostronna, bd: f() jest wartoci prawostronn
string& r3 {"Princeton"};      // referencja lewostronna, bd: nie mona wiza z obiektami tymczasowymi
string&& rr1 {f()};            // referencja prawostronna, wizanie rr1 z wartoci prawostronn (obiektem tymczasowym)
string&& rr2 {var};            // referencja prawostronna, bd: var jest wartoci lewostronn
string&& rr3 {"Oxford"};       // rr3 odnosi si do tymczasowego obiektu zawierajcego napis "Oxford"

const string cr1& {"Harvard"}; // OK: utworzenie obiektu tymczasowego i zwizanie go z cr1
---------------
string f(string&& s)
{
    if (s.size())
        s[0] = toupper(s[0]);
    return s;
}
---------------
template<class T>
swap(T& a, T& b) // "zamiana w starym stylu"
{
    T tmp {a};   // teraz mamy dwie kopie a
    a=b;         // teraz mamy dwie kopie b
    b = tmp;     // teraz mamy dwie kopie tmp (znanej te jako a)
}
---------------
template<class T>
void swap(T& a, T& b)            // "Doskonaa zamiana" (no prawie)
{
    T tmp {static_cast<T&&>(a)}; // w inicjacji mona zapisa warto a
    a = static_cast<T&&>(b);     // w przypisaniu mona zapisywa w b
    b = static_cast<T&&>(tmp);   // w przypisaniu mona zapisywa w tmp
}
---------------
template<class T> class vector {
    //...
    vector(const vector& r); // konstruktor kopiujcy (kopiuje reprezentacj r)
    vector(vector&& r);      // konstruktor przenoszcy ("podkrada" reprezentacj z r)
};

vector<string> s;
vector<string> s2 {s};        // s jest wartoci lewostronn, a wic uyty bdzie konstruktor kopiujcy
vector<string> s3 {s+"tail"); // s+"tail" jest wartoci prawostronn, wic uyty zostanie konstruktor przenoszcy
---------------
template<class T>
void swap(T& a, T& b) // "doskonaa zamiana" (prawie)
{
    T tmp {move(a)};  // przeniesienie z a
    a = move(b);      // przeniesienie z b
    b = move(tmp);    // przeniesienie z tmp
}
---------------
void f(vector<int>& v)
{
    swap(v,vector<int>{1,2,3}); // zastpuje elementy wektora v wartociami 1, 2, 3
    //...
}
---------------
template<class T> void swap(T&& a, T& b);
template<class T> void swap(T& a, T&& b)
---------------
void f(string& s, vector<int>& v)
{
    s.shrink_to_fit();     // s.capacity()==s.size()
    swap(s,string{s});     // s.capacity()==s.size()
    v.clear();             // kasuje zawarto v
    swap(v.vector<int>{}); // kasuje zawarto v
    v = {};                // kasuje zawarto v
}
---------------
using rr_i = int&&;
using lr_i = int&;
using rr_rr_i = rr_i&&; // int && && to int&&
using lr_rr_i = rr_i&;  // int && & to int&
using rr_lr_i = lr_i&&; // int & && to int&
using lr_lr_i = lr_i&;  // int & & to int&
---------------
int && & r = i;
---------------
void fp(char*p)
{
    while (*p)
        cout << ++*p;
}

void fr(char& r)
{
    while (r)
        cout << ++r; // ups: zwikszenie wskazywanego znaku, nie referencji
                     // to prawie nieskoczona ptla!
}

void fr2(char& r)
{
    char*p = &r;     // utworzenie wskanika do obiektu, do ktrego odnosi si referencja
    while (*p)
        cout << ++*p;
}
---------------
template<class T> class Proxy {  // Proxy odnosi si do obiektu, ktrym jest inicjowany
    T& m;
public:
    Proxy(T& mm) :m{mm} {}
    // ...
};

template<class T> class Handle { // Handle odnosi si do swojego biecego obiektu
    T*m;
public:
    Proxy(T*mm) :m{mm} {}
    void rebind(T*mm) { m = mm; }
    // ...
};
---------------
Matrix operator+(const Matrix&, const Matrix&); // OK
Matrix operator-(const Matrix*, const Matrix*); // bd: brak argumentu typu zdefiniowanego
                                                // przez uytkownika

Matrix y, z;
// ...
Matrix x = y+z;    // OK
Matrix x2 = &y-&z; // bd i brzydkie
---------------
int x, y;
string& a1[] = {x, y};         // bd: tablica referencji
string*a2[] = {&x, &y};        // OK
vector<string&> s1 = {x , y};  // bd: wektor referencji
vector<string*> s2 = {&x, &y}; // OK
---------------
void fp(X*p)
{
    if (p == nullptr) {
        // brak wartoci
    }
    else {
        // dziaania przy uyciu *p
    }
}

void fr(X& r) // typowy styl
{
    // zaoenie, e r jest poprawny, i uycie go
}
---------------
void fr2(X& r)
{
    if (&r == &nullX) { // albo r==nullX
        // brak wartoci
    }
    else {
        // dziaania przy uyciu r
    }
}
---------------
char*ident(char*p) { return p; }
char& r {*ident(nullptr)}; // niepoprawny kod