Programowanie w C++ w praktyce - ADB · • C++11 (C++0x) – rozszerzenia zarówno składni...

38
Adam Stolcenburg Programowanie w C++ w praktyce

Transcript of Programowanie w C++ w praktyce - ADB · • C++11 (C++0x) – rozszerzenia zarówno składni...

Page 1: Programowanie w C++ w praktyce - ADB · • 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

Adam Stolcenburg

Programowanie w C++ w praktyce

Page 2: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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: Programowanie w C++ w praktyce - ADB · • 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

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

Page 38: Programowanie w C++ w praktyce - ADB · • 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

Dziękuję