Développer en natif avec C++11

Preview:

DESCRIPTION

Articulé autour de C++ 11, cette session amène celui qui y assiste aux fondamentaux du développement logiciel : libraries, dépendances, TR1 et C++0X les fondations de C++ 11, runtime C alias CRT, runtime C++ alias STL, agilité en C++, ALM en C++, Windows 8 et C++, C++ et Windows 8 avec le nouveau modèle COM nommé WRL.

Citation preview

Développement natif en C++

Christophe Pichaud – ArchitecteSogeti

Loïc Joly – ArchitecteCAST

Code / Développement

Design/Général

Mobilité/Consumer/B2C

Code/ Dev Office / B2B / LOB / entreprise

Architecture / Azure / Cloud

Serveurs / Entreprise / Réseaux / IT

Phone / Mobilité

Gaming / Divertissement

C++11 LES GRANDS THÈMESChapitre 1

Développement natif en C++ 11

C++11 est comme un nouveau langage Evolutions du langage – standard C++ 11

Changer le codage avec des styles/guidances/idioms. C’est ce qui définit le nouveau langage

Pourquoi une session C++ ?

Pourquoi le C++ ?Optimiser Exemple C++ ?

Le temps/coût de développement

Interface d’accès BdD Non

Le temps d’exécution Jeux, temps réel Oui

Le coût hardware Ferme de serveurs Oui

L’énergie nécessaire Informatique mobileCentre de calcul

Oui

• Dans de nombreux domaines, le coût de développement est devenu très faible face au coût d’exploitation

Pourquoi choisir C++ ?

“The going word at Facebook is that ‘reasonably written C++ code just runs fast,’ which underscores the enormous effort spent at optimizing PHP and Java code. Paradoxically, C++ code is more difficult to write than in other languages, but efficient code is a lot easier.” – Andrei Alexandrescu

The C++ Standards Commitee http://www.open-std.org/jtc1/sc22/wg21/

2011 : Approbation du standard C++0x Amélioration de l’implémentation dans « VC++ 11 »

2008: Draft pour C++0x Implémentation (partielle) dans Visual C++ 2010

2005: TR1= Library Technical Report 1 Visual C++ 2008 + TR 1

2003: TC1 = corrections C++98 1998: C++ devient un standard ISO (« C++98 »)

La roadmap C++

TR1.. C++0x.. C++ 11

TR1 - Technical Report 1shared_ptr<T>

weak_ptr<T>

unique_ptr<T>

regex

tuple

array

C++ 0xlambdas

r-value reference

auto

decltype

static_assert

Thread

mutex

future<T>

vector<vector<int>>

variadic templates

C++, mythes et réalités

Template meta-programming

Des macros et de goto !

C’est du C !

Un langage orienté objet compliqué !

Bas niveau !

Non sécurisée, dangereux !

Code dur à maintenir

Code crado mais je continue sur le même modèle…

Compliqué à apprendre !

Peu productif !

cast

new / delete

pointeurs

Orienté objet

Un bon code

principes et techniques

Interfaces richesStructure de données

compactes et efficaces

le style C++ 11

gestion des erreurs

Le C++11 permet de faire du code Clean, Safe, Fast.Clean & Safe : le nouveau style moderneFast : l’a toujours été

Evolution du style C++

Aperçu des différences

Then Nowcircle* p = new circle( 42 );

vector<shape*> vw;load_shapes( vw );

for( vector<circle*>::iterator i = vw.begin(); i != vw.end(); ++i ) { if( (*i)->weight() > 100 ) cout << **i << “ is a match\n”;}

for( vector<circle*>::iterator i = vw.begin(); i != vw.end(); ++i ) { delete *i;}

delete p;

auto p = make_shared<circle>( 42 );

auto vw = load_shapes();

for( auto& s : vw ) { if( s->weight() > 100 ) cout << *s << “ is a match\n”;}

T* shared_ptr<T>

new make_shared

Pas de delete. Gestion automatique du cycle de

vie. exception-safe

range-for

auto type deduction

not exception-safe

missing try/catch, __try/__finally

return by value + move

+ auto again to deduce

vector<shared_ptr<shape>>

Plus grosse « difficulté du C++ » : la gestion de mémoireIl n’y a pas de manière unique d’allouer la mémoire en C++Heureusement : RAII= Resource Acquisition Is Initialization

Destruction déterministe (i.e. pas besoin de « using ») Applicable à toutes les ressources « précieuses :

Mémoire fichiers, sockets, handles Windows

Gestion de la mémoire

“C++ is the best language for garbage collection principally because it creates less garbage.”

Bjarne Stroustrup

Effective C++, Third Edition (2005) by Scott Meyers: "shared_ptr may be the most widely useful

component in TR1."

C++ Coding Standards (2005) by Herb Sutter and Andrei Alexandrescu: "Store only values and smart pointers in containers.

To this we add: If you use [Boost] and [C++TR104] for nothing else, use them for shared_ptr."

Paroles d’experts !

Un template C++ disponible dans <memory>Basé sur le comptage de référencesGain de productivité & robustesse importants avec impact minimal sur les perfsCompatible avec les conteneurs STLCompatible avec le polymorphisme :

shared_ptr<Derived> est convertible en shared_ptr<Base> Ne casse pas le mécanisme de comptage des références Besoin de convertir (cast) ?

static_pointer_cast<Derived>(spBase) dynamic_pointer_cast<Derived>(spBase)

Caractéristiques de shared_ptr<T>

Possibilité d’instancier shared_ptr<T> sans modifier TLa gestion des références (uses/weaks) est dans le shared_ptrFonctionne avec les types prédéfinis: shared_ptr<int>S’incorpore dans le code sans modifier les types existantsUn même type peut être manipulé parfois via un shared_ptr et d’autres fois via d’autres mécanismes

shared_ptr est Non-Intrusif

VS 2008 SP1 (VC9 SP1): shared_ptr<T> sp(new T(args)); shared_ptr<T> sp(new T(args), del, alloc);

VS 2010 (VC10): auto sp = make_shared<T>(args); auto sp = allocate_shared<T>(alloc, args);

Simple et élegant Écrire le type T une seule fois

Robuste Pas de fuite avec shared_ptr

Efficace Allocation de mémoire dynamique standard

make_shared<T>()

Une seule référence de l’objetunique_ptr<Cat> c(new Cat);unique_ptr<Cat> c2(Cat::Load(…));

Remplace auto_ptr, qui est obsolèteCompatible avec les collections STL (containers) Non copiable mais déplaçable

unique_ptr<Cat> c(new Cat); unique_ptr<Dog> d; d.reset(new Dog); unique_ptr<Monster> m_src(new Monster); unique_ptr<Monster> m_dest(move(m_src));

unique_ptr<T>

DELETE

C++ 11 : Best-Of

vector<string> v;v.push_back( “Geddy Lee” );

array<string,50> a;

Containers STLmap<string, string> phone;

phone[“Alex Lifeson”] = “+1 (416) 555-1212”;

multimap<string, string> phone;

phone[“Neil Peart”] = “+1 (416) 555-1212”;

phone[“Neil Peart”] = “+1 (905) 555-1234”;

unordered_map<string, string> phone;

phone[“Alex Lifeson”] = “+1 (416) 555-1212”;

unordered_multimap<string, string> phone;

phone[“Neil Peart”] = “+1 (416) 555-1212”;

phone[“Neil Peart”] = “+1 (905) 555-1234”;

container par défaut: vector

compact, efficace, cache, préfetch

dictionary: map (arbre) ou

unordered_map (hash)

vecteur de taillle fixe: array

compact, efficace, cache, préfetch

Itération au travers un “range”

void f(vector<double>& v) {

for (auto x : v) cout << x << '\n';

for (auto& x : v) ++x; // using a reference to allow us to change the value

}

Boucle for avec range

nullptr exprime un pointeur nulCe n’est pas un int

class Foo {public: Foo(const char *s); Foo(int n);}…Foo f(NULL);Foo f(nullptr);

nullptr

NULL

La problème d’espace est résolu

list<vector<string>> lvs;

Syntax Error de template<T>

une classe possède par défaut 5 opérations Un constructeur par copie Un opérateur de copie Un constructeur de move Un opérateur de move Un destructeur

Conseil si vous implémentez une de ces méthodes, alors implémentez-

les toutes.

Une classe C++11 type

Conversion de enum automatiquement en int et enum fortement typé

enum Alert { green, yellow, election, red }; // traditional enum enum class Color { red, blue }; // scoped and strongly typed enum

// no export of enumerator names into enclosing scope // no implicit conversion to int

enum class TrafficLight { red, yellow, green }; Alert a = 7; // error (as ever in C++) Color c = 7; // error: no int->Color conversion int a2 = red; // ok: Alert->int conversion int a3 = Alert::red; // error in C++98; ok in C++0x int a4 = blue; // error: blue not in scope int a5 = Color::blue; // error: not Color->int conversion Color a6 = Color::blue; // ok

enum & enum classclass enum

Indiquer explicitement un opérateur de copie par défault

class Y { // ... Y& operator=(const Y&) = default; // default copy semantics Y(const Y&) = default; }

Indiquer l’interdiction de la copieclass X { // ... X& operator=(const X&) = delete; // Disallow copying X(const X&) = delete; };

=default et =delete

Le mécanisme de constexpr Permet d’exprimer généralement des

expressions constantes Permet d’utiliser les types spécifiques Fournit l’assurance que l’initialisation est fournie

au moment de la compilationAttention constexpr ne remplace pas const (et vice versa)

constexpr

Le mécanisme de decltype(E) permet d’avoir une expression qui peut être utilisée dans une déclaration Concept utilisé en programmation générique Appelée aussi “typeof”

Conseil Préférez l’utilisation de auto

decltype(E)

Maintenant, on peut écrire celavector<double> v = { 1, 2, 3.456, 99.99 };

list<pair<string,string>> languages = { {"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"} };

map<vector<string>,vector<int>> years = { { {"Maurice","Vincent", "Wilkes"},{1913, 1945, 1951, 1967, 2000} }, { {"Martin", "Ritchards"} {1982, 2003, 2007} }, { {"David", "John", "Wheeler"}, {1927, 1947, 1951, 2004} } };

L’utilisation de {} est possible via une fonction (souvent par un constructeur) qui accepte un argument std::initializer_list<T>

vector (std::initializer_list<E> s) // initializer-list constructor

Initialisation des listes

Si deux ctor font la même chose, il faut une routine init() et faire un appel dans chaque ctor…Maintenant, il est possible décrire cela

class X { int a; public: X(int x) { if (0<x && x<=max) a=x; else throw bad_X(x); } X() :X{42} { } X(string s) :X{lexical_cast<int>(s)} { } // ... };

Délégation de constructeur

Seules les membres statiques peuvent être initialisés et avec des expressions constantes…Maintenant, il est possible décrire cela

class A { public: A() {} A(int a_val) : a(a_val) {} A(D d) : b(g(d)) {} int a = 7; int b = 5; private: HashingFunction hash_algorithm{"MD5"}; // Cryptographic hash to be applied to all A

instances std::string s{"Constructor run"}; // String indicating state in object lifecycle };

Init. de membres de classes

Un type long mais qui est very long. Au moins 64 bits

long long x = 9223372036854775807LL;

long long (64 bits)

Un typedef pour les templatesPermet une écriture plus élégante des templates dans le code

template<class T> using Vec = std::vector<T,My_alloc<T>>; // standard vector using my allocator Vec<int> fib = { 1, 2, 3, 5, 8, 13 }; // allocates elements using My_alloc

Marche aussi avec le code style-Ctypedef void (*PFD)(double); // C style using PF = void (*)(double); // using plus C-style type

template typedef

Avant… vector<shared_ptr<CPolygon>>::iterator beg =

polys.begin(); long et fastidieux à écrire !

Maintenant, avec « auto » auto i = polys.begin(); Type déduit par le compilateur Equivalent de « var » en C# Evite aussi certaines conversions implicites en cas

d’erreur sur le type

auto

map<string, string> m;const regex r("(\\w+) (\\w+)");for (string s; getline(cin, s); ) { smatch results; if (regex_match(s, results, r)) { m[results[1]] = results[2]; }}for (auto i = m.begin(); i != m.end(); ++i) { cout << i->second << " are " << i->first << endl;}// Au lieu de map<string, string>::iterator

auto

auto utilise les règles de détection d’arguments des templates

const auto * p = foo et const auto& r = bar compilentauto... Réduit le code et améliore la lisibilité du code important Permet d’éviter les erreurs de types, troncations, … Améliore la généricité du code sans le superflu des

expressions intermédiaires Fonctionne très bien avec les types comme les lambdas

auto: pourquoi l’utiliser ?

vector<int> v;

for (auto i = v.begin(); i != v.end(); ++i) { // i is vector<int>::iterator}

for (auto i = v.cbegin(); i != v.cend(); ++i) { // i is vector<int>::const_iterator}

cbegin(), cend(), crbegin(), crend()

Les références de Rvalue permettent deux choses importantes : Déplacement (move semantics) : pour la performance Perfect forwarding: pour la généricité

= une seule fonction générique qui accepte des arguments quelconques et les transmet de manière transparente à une autre fonction en préservant leur nature (const, lvalue, rvalue, etc)

Ex : make_sharedLes patterns de déplacement et de perfect forwarding sont simples à mettre en oeuvreMais ils s’appuient sur de nouvelles règles d’initialisation, de résolution de surcharge, de déduction des paramètres des templates, etc.Les conteneurs STL sont “move aware”

Références de RValue

set<widget> load_huge_data() { set<widget> ret; // … load data and populate ret … return ret;}widgets = load_huge_data();

Efficacité du déplacement

vector<string> v = IfIHadAMillionStrings();v.insert( begin(v)+v.size()/2, “tom” );v.insert( begin(v)+v.size()/2, “richard” );v.insert( begin(v)+v.size()/2, “harry” );

HugeMatrix operator+( const HugeMatrix&, const HugeMatrix&);hm3 = hm1+hm2;

Efficace: pas de copie en profondeur et pas

besoin du contournement

allocation dynamique + retour de pointeur

Efficace, pas de copie en

profondeur

(juste les assignements de

pointeurs

Efficace, pas de copie supplémentaire

class my_class { unique_ptr<BigHugeData> data;public: my_class( my_class&& other ) : data( move( other.data ) ) { } my_class& operator=( my_class&& other ) { data = move( other.data ); } ::: void method() { if( !data ) throw “moved-from object”; ::: }};

Mécanique du Move / Value Types

move construction

move assignment

check (if appropriate)

Copy ? Move: Also enable move if it can be cheaper than a deep

copy.

Move / Copy: Some non-value types are naturally move-only.

Example: unique_ptr.

<algorithm> bool all_of/any_of/none_of(InIt, InIt, Pred) InIt find_if_not(InIt, InIt, Pred) OutIt copy_n(InIt, Size, OutIt) OutIt copy_if(InIt, InIt, OutIt, Pred) bool is_partitioned(InIt, InIt, Pred) pair<Out1, Out2> partition_copy(InIt, InIt, Out1, Out2, Pred) FwdIt partition_point(FwdIt, FwdIt, Pred) bool is_sorted(FwdIt, FwdIt, Comp?) FwdIt is_sorted_until(FwdIt, FwdIt, Comp?) bool is_heap(RanIt, RanIt, Comp?) RanIt is_heap_until(RanIt, RanIt, Comp?) pair<FwdIt, FwdIt> minmax_element(FwdIt, FwdIt, Comp?)

<numeric> void iota(FwdIt, FwdIt, T)

<iterator> InIt next(InIt, Distance) BidIt prev(BidIt, Distance)

Nouveautés des algorithmes

Parcours simples Exemple : for_each = le plus simple

Parcours avec transformations Exemple : copy = copie tous les éléments

répondant à une conditionTris Exemples : sort, stable_sort, lower_bound

Algorithmes : trois catégories

All ofAny ofNone ofFor eachFindFind endFind firstAdjacent FindCountMismatchEqualIs permutationSearch

Parcours simples

template<class InputIterator, class Predicate>InputIterator find_if(InputIterator first, InputIterator last, Predicate pred);

Retourne le premier élément vérifiant le prédicatPredicate : Fonctions prédéfinies Classe surchargeant operator() Lambda

Exemple : Find first

CopyMoveSwapTransformReplaceFillGenerateRemoveUniqueReverseRotateRandom shufflePartitions

Transformations

template<class InputIterator, class OutputIterator, class UnaryOperation>OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op);

Exemple: impression de tous les éléments d’un conteneur :

copy(points.begin(), points.end(), ostream_iterator<CPoint>(cout, "\n" ));

Exemple Transform

SortStable_sortPartial_sortNth elementBinary search : lower_bound, upper_boundMerge

Tri et assimilés

template<class RandomAccessIterator, class Compare>void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);

Trie les éléments selon « comp »Comp = ordre strict (< ou > et non £ ou ³)

bool PlusHaut(CPoint &pt1, CPoint &pt2){ return pt1.Y() > pt2.Y();}sort(points.begin(), points.end(), PlusHaut);

Exemple : sort

Fonctions simples pas paramétrables

Classes Lourdes à écrire Pb de localité

Lambdas Le meilleur des deux mondes

Lambdas

Les Lambda Expressions définissent et construisent des classes fonctions anonymesLa Lamba Expressionfor_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

Est équivalente àstruct LambdaFunctor { void operator()(int n) const { cout << n << " "; }};…for_each(v.begin(), v.end(), LambdaFunctor());

Le B.A. BA des lambdas

Une lambda peut contenir plusieurs instructions

void par défaut

Lambda Stateless: [] signifie pas de capture du contexteCapture-list : utilisation de variables extérieures à la lambda

v.erase(remove_if(v.begin(), v.end(), [x, y](int n) { return x < n && n < y; }), v.end());

Les copies capturées « survivent » à leur contexte

Possibilité de capture par référence

Compléments

Maintenant, on peut écrire celavector<double> v = { 1, 2, 3.456, 99.99 };

list<pair<string,string>> languages = { {"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"} };

map<vector<string>,vector<int>> years = { { {"Maurice","Vincent", "Wilkes"},{1913, 1945, 1951, 1967, 2000} }, { {"Martin", "Ritchards"} {1982, 2003, 2007} }, { {"David", "John", "Wheeler"}, {1927, 1947, 1951, 2004} } };

L’utilisation de {} est possible via une fonction (souvent par un constructeur) qui accepte un argument std::initializer_list<T>

vector (std::initializer_list<E> s) // initializer-list constructor

Initialisation des listes

Si deux ctor font la même chose, il faut une routine init() et faire un appel dans chaque ctor…Maintenant, il est possible d’écrire cela

class X { int a; public: X(int x) { if (0<x && x<=max) a=x; else throw bad_X(x); } X() :X{42} { } X(string s) :X{lexical_cast<int>(s)} { } // ... };

Délégation de constructeur

Seules les membres statiques peuvent être initialisés et avec des expressions constantes…Maintenant, il est possible d’écrire cela

class A { public: A() {} A(int a_val) : a(a_val) {} A(D d) : b(g(d)) {} int a = 7; int b = 5; private: HashingFunction hash_algorithm{"MD5"}; // Cryptographic hash to be applied to all A

instances std::string s{"Constructor run"}; // String indicating state in object lifecycle };

Init. de membres de classes

TESTS UNITAIRES DANS VISUAL STUDIO

Chapitre 2

Développement natif en C++ 11

• Tests unitaires 100% natifs intégrés à l’IHM• Framework de test

– Fourni par Microsoft– Google tests– xUnit++– Autre ?

blogs.msdn.com/b/bhuvaneshwari/archive/2012/03/13/authoring-a-new-visual-studio-test-adapter.aspx

• Couverture de code

Tests unitaires natifs

Programme (.exe)

Tests unitaires natifs : Architecture

Programme (.exe)

Bibliothèque 1 (.lib)

Bibliothèque 2

(.dll)

Tests unitaires 1

(.dll)

Tests unitaires 2

(.dll)

Exécuteur de tests (.exe)

Programme (.exe)

VISUAL C++11 ET NOV 2012 CTPChapitre 3

Développement natif en C++ 11

• CTP = Version version beta– Incomplet : Uniquement le compilateur (pas la

SL)– Pas pour utilisation en prod– Bugs possibles– Activé explicitement

• 6 nouveautés• Des démos !

Visual C++ compiler Nov 2012 CTP

• 6 nouveautés– Littéraux de chaîne de caractères bruts– Initialisation uniforme et initializer_lists– Délégation de constructeurs– Opérateurs de conversion explicites– Templates variadiques– Arguments template par défaut pour les

fonctions template

Visual C++ compiler Nov 2012 CTP

• Bénéfices– Code C++ plus simple, plus rapide à écrire– Meilleure compatibilité avec gcc, clang…• Code portable avec moins de restrictions• Plus large choix de bibliothèques

• À quand la version finalisée ?• Le chemin n’est pas fini…

Visual C++ compiler Nov 2012 CTP

• N’oubliez pas : Le nouveau portail du C++ :

www.isocpp.org

Questions / Réponses

The Space needle

Exemple de slide photo

Design

Developpement

Exemple de code<common:LayoutAwarePage x:Name="pageRoot" x:Class="App3.GroupedItemsPage" DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App3" xmlns:data="using:App3.Data" xmlns:common="using:App3.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">

Réseaux

• Exemple de Pie chart pour une session Réseaux

Exemple de graphe

Formez-vous en ligne

Retrouvez nos évènements

Faites-vous accompagner gratuitement

Essayer gratuitement nos solutions IT

Retrouver nos experts Microsoft

Pros de l’ITDéveloppeurs

www.microsoftvirtualacademy.com

http://aka.ms/generation-app

http://aka.ms/evenements-developpeurs

http://aka.ms/itcamps-france

Les accélérateursWindows Azure, Windows Phone,

Windows 8

http://aka.ms/telechargements

La Dev’Team sur MSDNhttp://aka.ms/devteam

L’IT Team sur TechNethttp://aka.ms/itteam

Recommended