Programowanie w C++ w praktyce - ADB · • C++11 (C++0x) – rozszerzenia zarówno składni...
Transcript of Programowanie w C++ w praktyce - ADB · • C++11 (C++0x) – rozszerzenia zarówno składni...
Adam Stolcenburg
Programowanie w C++ w praktyce
page 2
Wersje języka C++
• C++98 – pierwsza wersja ustandaryzowana przez organizacje ISO• C++03 – poprawki problemów zgłoszonych do wersji C++98• TR1 – w 2005 komisja standaryzacyjna C++ wypuściła raport techniczny opisujący rozszerzenia jakie
planuje wprowadzić w następnej wersji standardu• C++11 (C++0x) – rozszerzenia zarówno składni języka jak i zawartości biblioteki standardowej,
biblioteka Boost miała znaczący wpław na kształt nowego standardu, niektóre biblioteki zostały bezpośrednio zaczerpnięte z bibliotek dostępnych w Boost, do bardziej znaczących rozszerzeń można zaliczyć:• standardowa biblioteka wątków• słowo kluczowe auto• uproszczona składnia pętli for• wyrażenia lambda• nowe kontenery
• C++14 (C++1y) – drobne rozszerzenia zmian wprowadzonych w wersji C++11 jak również poprawki błędów
• C++17 (C++1z) – wersja planowana na rok 2017• w zależności od możliwości kompilatora istnieje możliwość wyboru wersji standardu, dla GCC oraz
Clang dostępna jest opcja -std=[wersja] (na przykład -std=c++11), gdzie [wersja] może przyjmować jedną z następujących wartości: c++98, c++03, c++0x, c++11, c++14, c++1z, c++17
http://www.cplusplus.com/info/history/
page 3
std::string
• zdefiniowany w nagłówku <string>• http://www.cplusplus.com/reference/string/string/• reprezentuje sekwencje znaków• interfejs zbliżony do standardowych kontenerów rozszerzony o możliwość operowania na łańcuchach znaków• znaki reprezentowane za pomocą typu char• może przechowywać sekwencje znaków również w formatach o zmiennej długości znaku jak UTF-8, lecz
również i w tym przypadku jego funkcje składowe operują z dokładnością do bajtów• różne strategie zarządzania pamięcią: http://info.prelert.com/blog/cpp-stdstring-
implementations#summarytable• ciekawe funkcje składowe
• reserve() – prealokuje pamięć• assign() – przypisuje nową wartość• append() – dokleja podaną wartość na koniec łańcucha• find(), rfind() – wyszukiwanie łańcucha• find_first_of(), find_last_of(), find_first_not_of(), find_last_not_of() – przeszukiwanie pod kątem zbioru znaków• substr() – generuje nowy obiekt będący podłańcuchem aktulanego (może alokować pamięć)• c_str() – zwraca wskaźnik do const char* kompatybilny z C (zakończony zerem).
page 4
std::string – sposób zarządzania pamięcią#include <string>
int main (int argc, char** argv) { // GCC 4.8.4 - 1 memory allocation, GCC 5.4.0 – 0 allocations std::string string_assign = "Hello World!";
// GCC 4.8.4 =c++11 - 3 allocations, -std=c++03 - 4 allocations, GCC 5.4.0 – 0 allocations std::string string_adding = std::string("Hello") + " " + "World" + "!";
// GCC 4.8.4 -std=c++11 - 30 allocations, -std=c++03 - 40 allocations, GCC 5.4.0 – 0 allocations std::string string_adding_in_loop; for (unsigned int i = 0; i < 10; ++i) { string_adding_in_loop = std::string("Hello") + " " + "World" + "!"; }
// GCC 4.8.4 - 1 memory allocation, GCC 5.4.0 – 0 allocations std::string no_reallocation; no_reallocation.reserve(12); for (unsigned int i = 0; i < 10; ++i) { no_reallocation.assign("Hello").append(" ").append("World").append("!"); }
return 0;}
page 5
std::string – niejawna konwersja#include <string>
#include <iostream>
bool isJPG(const std::string& file_name) {
bool result = false;
std::string::size_type pos = file_name.rfind(".");
if ((pos != std::string::npos) && (file_name.size() - pos == 4)) {
result = file_name.find("jpg", pos + 1) == pos + 1;
}
return result;
}
int main (int argc, char** argv) {
// string literal is implicitly converted to std::string which most probably requires memory allocation
std::cout << isJPG("this_is_a_file_with_long_name.jpg") << std::endl;
std::string file_name = "this_is_a_second_file_with_long_name.jg";
// no additional memory allocation when function is called with std::string as parameter
std::cout << isJPG(file_name) << std::endl;
return 0;
}
page 6
boost::string_ref, std::string_view
• boost::string_ref• dostępny od wersji boost 1.53• zdefiniowany w nagłówku <boost/utility/string_ref.hpp>• http://www.boost.org/doc/libs/1_63_0/libs/utility/doc/html/string
_ref.html• std::string_view
• dostępny od wersji C++17• zdefiniowany w nagłówku <string_view>• http://en.cppreference.com/w/cpp/string/basic_string_view
• reprezentuje sekwencje znaków bez ich własności• przechowuje wskaźnik do początku łańcucha oraz jego długość• interfejs zbliżony do std::string
page 7
boost::string_ref – praktyczne zastosowanie (1)#include <boost/utility/string_ref.hpp>
#include <iostream>
bool isJPG(boost::string_ref file_name) {
bool result = false;
boost::string_ref::size_type pos = file_name.rfind(".");
if (pos != std::string::npos) {
result = file_name.substr(pos + 1) == "jpg";
}
return result;
}
int main (int argc, char** argv) {
// no memory allocation
std::cout << isJPG("file.jpg") << std::endl;
std::string file_name = "file.jg";
// no memory allocation
std::cout << isJPG(file_name) << std::endl;
return 0;
}
page 8
boost::string_ref – praktyczne zastosowanie (2)#include <boost/utility/string_ref.hpp>
#include <cstdio>
bool isKnownToken(boost::string_ref token) {
static boost::string_ref known_tokens[] = { "t1", "t2", "t3" };
for (auto known_token : known_tokens) {
if (known_token == token) return true;
}
return false;
}
int main() {
boost::string_ref tokens_to_check_csv = "tn,t4,t1,t5,t3,t2,ty,t2";
std::size_t known_tokens = 0, begin = 0, cpos = 0;
do {
cpos = tokens_to_check_csv.substr(begin).find(',');
known_tokens += isKnownToken(tokens_to_check_csv.substr(begin, cpos));
begin += cpos + 1;
} while (cpos != boost::string_ref::npos);
return 0;
}
page 9
boost::optional, std::optional
• boost::optional• dostępny od wersji boost 1.30• zdefiniowany w nagłówku <boost/optional.hpp>• http://www.boost.org/doc/libs/1_63_0/libs/optional/doc/html/index.html
• std::optional• dostępny od wersji C++17• zdefiniowany w nagłówku <optional>• http://en.cppreference.com/w/cpp/utility/optional
• reprezentuje wartość która może istnieć, lecz jest opcjonalna• w razie potrzeby wartość jest inicjalizowana w ramach pamięci zarezerwowanej
przez opcjonalny obiekt• wykorzystywany jako wartość zwracana przez funkcje które mogą się nie
powieść• posiada operator konwersji do bool umożliwiający sprawdzenie czy obiekt
posiada zainicjalizowaną wartość
page 10
boost::optional – podstawowe zastosowanie#include <boost/optional.hpp>
#include <boost/utility/string_ref.hpp>
#include <iostream>
#include <cstdlib>
boost::optional<unsigned long> convert(boost::string_ref value) {
boost::optional<unsigned long> result;
if (value.find_first_not_of("0123456789") == boost::string_ref::npos) {
result = strtoul(value.data(), 0, 10);
}
return result;
}
void check(boost::string_ref value) {
if (boost::optional<unsigned long> result = convert(value)) {
std::cout << value.data() << " converted to: " << *result << std::endl;
} else {
std::cout << value.data() << " not converted" << std::endl;
}
}
int main (int argc, char** argv) {
check("0");
check("1234t");
return 0;
}
page 11
boost::optional – inicjalizacja obiektów#include <boost/optional.hpp>
#include <iostream>
class Zoo {
int m_people;
int m_animals;
public:
Zoo(int people, int animals) : m_people(people), m_animals(animals) { }
void print() {
std::cout << m_people << " people and " << m_animals << " animals" << std::endl;
}
};
int main (int argc, char** argv) {
boost::optional<Zoo> zoo; // zoo is empty
// available only in boost
zoo = boost::in_place(10, 20); // zoo is constructed
zoo->print();
zoo = boost::none; // zoo is empty
// available since boost 1.56 and in std::optional
zoo.emplace(10, 12); // zoo is constructed
boost::optional<Zoo> zoo2 = zoo; // object is copied
return 0;
}
page 12
boost::optional – opóźniona inicjalizacja składowych#include <boost/optional.hpp>
class School {
class Person {
std::string m_name;
int m_age;
public:
Person(const std::string& name, int age) : m_name(name), m_age(age) { }
};
boost::optional<Person> m_principal;
public:
School() { }
void init(const std::string& principal_name, int principal_age) {
m_principal = boost::in_place(principal_name, principal_age);
}
};
int main() {
School school;
school.init("Principal", 54);
return 0;
}
page 13
boost::optional – prealokacja pamięci kontenerów#include <boost/optional.hpp>
#include <vector>
#include <iostream>
struct Person {
std::string m_name;
int m_age;
Person(const std::string& name, int age) : m_name(name), m_age(age) { }
};
int main() {
std::vector< boost::optional<Person> > people(10);
int age = 40;
for (auto& person : people) {
person = boost::in_place("Name", age++);
}
for (auto& person : people) {
std::cout << person->m_name << " " << person->m_age << "\n";
}
return 0;
}
page 14
boost::optional – domyślna wartość#include <boost/optional.hpp>
#include <iostream>
int sum(int val1, int val2,
boost::optional<int> val3 = boost::none,
boost::optional<int> val4 = boost::none) {
return val1 + val2 + val3.get_value_or(0) + val4.get_value_or(0);
}
int main (int argc, char** argv) {
std::cout << sum(1, 2) << std::endl;
std::cout << sum(1, 2, 3) << std::endl;
std::cout << sum(1, 2, 3, 4) << std::endl;
return 0;
}
page 15
boost::shared_ptr, std::shared_ptr
• boost::shared_ptr• dostępny od wersji boost 1.23• zdefiniowany w nagłówku <boost/optional.hpp>• http://www.boost.org/doc/libs/1_63_0/libs/optional/doc/html/index.html
• std::shared_ptr• dostępny od wersji C++11• zdefiniowany w nagłówku <memory>• http://www.cplusplus.com/reference/memory/shared_ptr/
• reprezentuje wskaźnik do obiektu posiadający jego własność• może dzielić własność przetrzymywanego obiektu z innymi obiektami typu shared_ptr• automatycznie niszczy przetrzymywany obiekt gdy ostatni obiekt typu shared_ptr
wskazujący na niego jest niszczony• bezpieczny w zastosowaniach wielowątkowych• posiada operator konwersji do bool umożliwiający sprawdzenie czy obiekt typu
shared_ptr przechowywuje inny obiekt
page 16
std::shared_ptr – zarządzanie obiektami#include <memory>
class Zoo {
int m_people;
int m_animals;
public:
Zoo(int people, int animals) : m_people(people), m_animals(animals) { }
};
int main (int argc, char** argv) {
std::shared_ptr<Zoo> zoo; // zoo is empty
if (!zoo) {
std::shared_ptr<Zoo> zoo2 = std::make_shared<Zoo>(10, 20); // zoo points to an object
zoo2.unique(); // true
zoo = zoo2; // zoo points to the same object as zoo2
zoo.unique(); // false
} // zoo2 is no longer in the scope, but the object to which it pointed still exists
zoo.unique(); // true
return 0;
}
page 17
std::shared_ptr – przykładowe użycie#include <memory>
#include <random>
class Integer {
int m_value;
public:
Integer(int value) : m_value(value) { }
};
class IntegerStore {
std::vector< std::shared_ptr<Integer> > m_selected_values;
public:
void checkValue(const std::shared_ptr<Integer>& value) {
static std::default_random_engine generator; static std::uniform_int_distribution<int> distribution(0, 1);
if (distribution(generator)) { m_selected_values.push_back(value); }
}
};
int main(int argc, char** argv) {
IntegerStore is1; IntegerStore is2;
for (int i = 0; i < 10; ++i) {
std::shared_ptr<Integer> value = std::make_shared<Integer>(i);
is1.checkValue(value);
is2.checkValue(value);
}
return 0;
}
page 18
boost::function, std::function
• boost::function• dostępny od wersji boost 1.23• zdefiniowany w nagłówku <boost/function.hpp>• http://www.boost.org/doc/libs/1_63_0/doc/html/function.html
• std::function• dostępny od wersji C++11• zdefiniowany w nagłówku <functional>• http://www.cplusplus.com/reference/functional/function/
• klasa opakowująca inne typy obiektów wywoływalnych• rodzaj wywołania zależny jedynie od sygnatury wywołania, a nie od
sygnatury wołania opakowanego obiektu wywoływalnego• posiada operator konwersji do bool umożliwiający sprawdzenie czy
obiekt przechowuje funkcje
page 19
std::function – obiekty wywoływalne#include <functional>
#include <iostream>
void print(long long value) { std::cout << value << std::endl; }
struct Print {
void operator()(float value) { std::cout << value << std::endl; }
};
struct Print2 {
void print(double value) { std::cout << value << std::endl; }
};
void call() { std::cout << __FUNCTION__ << std::endl; }
int main(int argc, char** argv) {
std::function<void (int)> f1 = print; // function
std::function<void (int)> f2 = &print; // function pointer
std::function<void (int)> f3 = Print(); // callable object
std::function<void (Print2*, int)> f4 = &Print2::print; // member function
std::function<void (int)> f5 = [] (int value) { // lambda expression
std::cout << value << std::endl;
};
std::function<void ()> f6 = std::bind(&call); // bind expression
std::function<void ()> f7 = [](){}; // empty lambda expression
return 0;
}
page 20
std::function – przykładowe użycie#include <functional>
#include <random>
#include <iostream>
int generateValue(std::function<bool (int)> callback) {
static std::default_random_engine generator; static std::uniform_int_distribution<int> distribution(0, 10);
int value = 0;
do {
value = distribution(generator);
} while (callback(value));
return value;
}
bool getGreaterThan5(int value) {
return value <= 5;
}
int main(int argc, char** argv) {
std::cout << generateValue(getGreaterThan5) << std::endl;
int out = 0;
std::cout << generateValue([&out](int value) { out = value; return value >= 5; }) << std::endl;
std::cout << out << std::endl;
return 0;
}
page 21
boost::bind, std::bind
• boost::bind• dostępny od wersji boost 1.25• zdefiniowany w nagłówku <boost/bind.hpp>• http://www.boost.org/doc/libs/1_63_0/libs/bind/doc/html/bind.html
• std::bind• dostępny od wersji C++11• zdefiniowany w nagłówku <functional>• http://www.cplusplus.com/reference/functional/bind/
• generuje wywoływalny obiekt łączący funkcję oraz jej argumenty• pozwala zarówno na dołączenie stałych wartości jako argumentów
opakowanej funkcji, jak również na przekazanie w dowolnej kolejności parametrów podawanych do wygenerowanego obiektu
page 22
std::bind – przykładowe użycie#include <functional>
#include <random>
#include <iostream>
int generateValue(std::function<bool (int)> callback) {
static std::default_random_engine generator; static std::uniform_int_distribution<int> distribution(0, 10);
int value = 0;
do {
value = distribution(generator);
} while (callback(value));
return value;
}
bool isGreaterOrEqualThan(int value, int compare_value) {
std::cout << value << " " << compare_value << std::endl;
return value >= compare_value;
}
int main(int argc, char** argv) {
std::cout << generateValue(std::bind(&isGreaterOrEqualThan, std::placeholders::_1, 4)) << std::endl;
std::cout << generateValue(std::bind(&isGreaterOrEqualThan, 1, 3)) << std::endl;
std::cout << generateValue(std::bind(&isGreaterOrEqualThan, 0, std::placeholders::_1)) << std::endl;
std::cout << generateValue(std::bind(&isGreaterOrEqualThan, std::placeholders::_1, std::placeholders::_1)) << std::endl;
return 0;
}
page 23
std::bind – współpraca z std::shared_ptr#include <functional>
#include <memory>
#include <algorithm>
#include <iostream>
struct Listener {
void notify(int value) {
std::cout << this << " " << value << "\n";
}
};
int main(int argc, char** argv) {
std::vector< std::function<void (int)> > listeners;
for (int i = 0; i < 10; ++i) {
std::shared_ptr<Listener> obj = std::make_shared<Listener>();
obj->notify(i);
listeners.push_back(std::bind(&Listener::notify, obj, std::placeholders::_1));
}
std::for_each(listeners.begin(), listeners.end(), [] (std::function<void (int)> listener) { listener(99); } );
return 0;
}
page 24
std::bind – efektywne przechowywanie wyrażeń#include <functional>
#include <iostream>
bool isGreaterOrEqual(int value, int compare_value) {
std::cout << value << " " << compare_value << std::endl;
return value >= compare_value;
}
int main(int argc, char** argv) {
auto is_greater_or_equal_four = std::bind(&isGreaterOrEqual, std::placeholders::_1, 4);
std::cout << (is_greater_or_equal_four(5) ? "true" : "false") << "\n";
auto is_greater_or_equal_four_v2 = [](int value) -> bool { return value >= 4; };
std::cout << (is_greater_or_equal_four_v2(5) ? "true" : "false") << "\n";
return 0;
}
page 25
std::list
• zdefiniowana w nagłówku <list>• http://www.cplusplus.com/reference/list/list/• lista dwukierunkowa• elementy są przechowywane w ramach odrębnych alokacji• automatycznie powiekszą się aby pomieścić przechowywane dane• stały czas wstawiania oraz usuwania elementów na dowolnej pozycji• niska wydajność spowodowana koniecznością iterowania się po kolejnych
elementach oraz słabemu wykorzystaniu cache procesora• nadaje się do przechowywania obiektów których tworzenie jest kosztowne• ciekawe funkcje składowe:• sort() – sortowanie elementów bez konieczności ich realokacji, ponieważ
zamieniana jest jedynie pozycja obiektu w kontenerze• swap() – zamienia miejscami zawartość dwóch list
page 26
std::list – zamiana miejscami zawartości list#include <list>
void swap(std::list<int>& list1, std::list<int>& list2) {
// do not do it like this
std::list<int> tmp = list1;
list1 = list2;
list2 = tmp;
}
int main() {
std::list<int> list1 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 };
std::list<int> list2 = { 1, 11, 21, 31, 41, 51, 61, 71, 81, 91 };
swap(list1, list2);
// do it like this
list1.swap(list2);
return 0;
}
page 27
std::vector
• zdefiniowany w nagłówku <vector>• http://www.cplusplus.com/reference/vector/vector/• odpowiednik tablicy, przechowuje dane w ciągłym obszarze pamięci (C++03)• stały czas dostępu do elementów za pomocą indeksów• automatycznie powiekszą się aby pomieścić przechowywane dane• dodawanie oraz usuwanie elementów na pozycji innej niż ostatnia wymusza
skopiowanie wszystkich elementów powyżej pozycji na której wykonujemy operacje
• wsadzanie elementów powyżej pojemności vectora wymusza skopiowanie wszystkich elementów
• ze względu na dobre wykorzystanie cache procesora w wielu zastosowaniach szybszy niż inne kontenery
• ciekawe funkcje składowe:• reserve() – prealokuje pamięć na potrzeby kontenera
page 28
std::vector – dodawanie elementów#include <vector>
#include <iostream>
int main (int argc, char** argv) {
// C++11 style
std::vector<int> vec = { 1, 2, 3, 4 };
for (auto value : vec) {
std::cout << value << std::endl;
}
// C++98 style
std::vector<int> vec2;
vec2.reserve(5); vec2.push_back(1); vec2.push_back(2); vec2.push_back(3); vec2.push_back(4);
for (std::vector<int>::iterator it = vec2.begin(); it != vec2.end(); ++it) {
std::cout << *it << std::endl;
}
for (std::vector<int>::size_type i = 0; i < vec2.size(); ++i) {
std::cout << vec2[i] << std::endl;
}
// valid but causes reallocation of all elements
vec.push_back(5);
// since space for 5 elements was reserved, still no memory reallocation
vec2.push_back(5);
return 0;
}
page 29
std::vector – usuwanie elementów#include <vector>
int main (int argc, char** argv) {
std::vector<int> vec3(10); // creates 10 default constructed elements
vec3[1] = 1;
vec3[2] = 2;
// efficient removal of all 0
int count = 0;
for (int i = 0; i < vec3.size(); ++i) {
if (vec3[i] != 0) {
vec3[count] = vec3[i];
++count;
}
}
vec3.resize(count);
// inefficient removal of all 0, efficient for containers which make one allocation per element
for (std::vector<int>::iterator it = vec3.begin(); it != vec3.end(); ) {
if (*it == 0) { it = vec3.erase(it); }
else { ++it; }
}
return 0;
}
page 30
std::vector – przechowywanie obiektów#include <vector>
#include <string>
class Person {
std::string m_name;
int m_age;
public:
Person(const std::string& name, int age) : m_name(name), m_age(age) { }
};
int main (int argc, char** argv) {
std::vector<Person> people;
// the object is copy constructed
people.push_back(Person("Adam", 20));
// C++11 specific function, the object is constructed inside container
// if needed in C++98 boost::container::vector may be used
people.emplace_back("Adam", 20);
return 0;
}
page 31
std::map
• zdefiniowany w nagłówku <map>• http://www.cplusplus.com/reference/map/map/• przechowuje elementy składające się z klucza i wartości• elementy są przechowywane posortowane według operatora < klucza,
lub podanego funktora porównującego• czas dostępu do elementów logarytmiczny względem ilości elementów• każdy element przechowywany jest jako odrębna alokacja, zatem
dodawania i usuwanie dowolnego elementu nie powoduje konieczności realokacji pozostałych
• wartości kluczy musza być unikalne• ciekawe funkcje składowe:
• find() - wyszukuje element na podstawie podanego klucza ze złożonością logarytmiczną względem ilości elementów
page 32
std::map – dodawanie elementów#include <map>
#include <iostream>
int main (int argc, char** argv) {
std::map<std::string, int> people = { // C++11 style initialization
{ "Pawel", 13 },
{ "Adam", 15 },
}; // { "Adam", 15 }, { "Pawel", 13 }
if (people["Gawel"] > 10) { // { "Adam", 15 }, { "Gawel", 0 }, { "Pawel", 13 }
std::cout << "Gawel > 10" << std::endl;
} else {
people["Gawel"] = 10; // { "Adam", 15 }, { "Gawel", 10 }, { "Pawel", 13 }
}
// in C++98 std::pair<std::map<std::string, int>::iterator, bool>
auto insert_result = people.insert(std::make_pair("Adam", 8)); // { "Adam", 15 }, { "Gawel", 10 }, { "Pawel", 13 }
if (insert_result.second == false) {
insert_result.first->second = 9; // { "Adam", 9 }, { "Gawel", 10 }, { "Pawel", 13 }
}
return 0;
}
page 33
std::map – wyszukiwanie i usuwanie#include <map>
int main (int argc, char** argv) {
std::map<std::string, int> people = { // C++11 style initialization
{ "Pawel", 13 }, { "Adam", 15 }, { "Gawel", 16 },
}; // { "Adam", 15 }, { "Gawel", 16 }, { "Pawel", 13 }
people["Adam"] = 14; // to be used only if the element exists or should be created
// in C++98 std::map<std::string, int>::iterator
auto end = people.find("Piotrek"); // end == people.end()
for (std::map<std::string, int>::iterator it = people.begin(); it != people.end();) {
if (it->second < 14) {
people.erase(it++); // needed in C++98
} else {
++it;
}
} // { "Adam", 15 }, { "Gawel", 16 }
people.erase("Adam"); // { "Gawel", 16 }
people.clear(); // map is empty
return 0;
}
page 34
Algorytmy
• zdefiniowane w nagłówku <algorithm>• http://www.cplusplus.com/reference/algorithm/• zestaw funkcji przeznaczonych do operowania na zbiorach danych których
elementy są dostępne za pomocą iteratorów lub wskaźników• algorymy zawsze operują na wartościach przechowywanych przez zbiór danych
i nigdy nie wpływają na strukturę kontenera• najczęściej używane algorytmy:• std::sort• std::lower_bound• std::upper_bound• std::for_each• std::find, std::find_if• std::remove, std::remove_if
• duża część algorytmów jest parametryzowana za pomocą obiektów wywoływalnych
page 35
std::sort, std::lower_bound, std::upper_bound#include <algorithm>
#include <vector>
static bool greater_than(int v1, int v2) {
return v1 > v2;
}
int main (int argc, char** argv) {
std::vector<int> vec = { 1, 5, 4, 3, 3 }; // C++11 style initialization
int tab[] = { 1, 5, 4, 3, 3 };
std::sort(vec.begin(), vec.end()); // 1 3 3 4 5
std::sort(tab, tab + sizeof(tab)/sizeof(tab[0])); // 1 3 3 4 5
// in case of C++98 std::vector<int>::iterator must be used instead of auto
auto greater_or_equal_to_3 = std::lower_bound(vec.begin(), vec.end(), 3); // *greater_or_equal_to_3 == 3
auto greater_than_3 = std::upper_bound(vec.begin(), vec.end(), 3); // *greater_than_3 == 4
std::sort(vec.begin(), vec.end(), greater_than); // 5 4 3 3 1
auto lower_or_equal_to_3 = std::lower_bound(vec.begin(), vec.end(), 3, greater_than); // *lower_or_equal_to_3 == 3
auto lower_than_3 = std::upper_bound(vec.begin(), vec.end(), 3, greater_than); // *lower_than_3 == 1
return 0;
}
page 36
std::for_each, std::find_if, std::remove_if#include <algorithm>
#include <vector>
#include <iostream>
int main(int argc, char** argv) {
std::vector<int> vec = { 1, 5, 4, 3, 3 }; // C++11 style initialization
auto new_end = std::remove(vec.begin(), vec.end(), 4); // 1 5 3 3 ?
// C++11 specific lambda expression
std::for_each(vec.begin(), new_end, [] (int value) { std::cout << value << std::endl; } ); // 1 5 3 3
struct IsLessThan3 { // may be defined inside function only in C++11
bool operator()(int val1) {
return val1 < 3;
}
};
new_end = std::remove_if(vec.begin(), new_end, IsLessThan3()); // 5 3 3 ? ? | vec.size() == 5
vec.erase(new_end, vec.end()); // 5 3 3 | vec.size() == 3
auto five = std::find(vec.begin(), vec.end(), 5); // *five == 5
auto end = std::find_if(vec.begin(), vec.end(), IsLessThan3()); // end == vec.end()
return 0;
}
page 37
Warto odwiedzić
• http://www.cplusplus.com• http://en.cppreference.com• http://www.boost.org• https://gcc.gnu.org/projects/cxx-status.html• http://clang.llvm.org/cxx_status.html
Dziękuję