Transcript auto

Développement natif en C++
Christophe Pichaud – Architecte
Sogeti
Loïc Joly – Architecte
CAST
Code / Développement
Chapitre 1
C++11 LES GRANDS THÈMES
Développement natif en C++ 11
Pourquoi une session C++ ?
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 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 mobile
Centre 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
La roadmap C++
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 »)
TR1..
C++0x.. C++
TR1 - Technical Report 1
C++ 0x
shared_ptr<T>
lambdas
weak_ptr<T>
r-value reference
unique_ptr<T>
auto
regex
decltype
tuple
static_assert
array
Thread
…
mutex
11
future<T>
vector<vector<int>>
variadic templates
…
C++, mythes et réalités
principes et techniques
gestion des erreurs
pointeurs
Code crado mais je continue
Un langage orienté objet
cast
sur le même modèle…
compliqué !
Orienté objet
Compliqué à apprendre !
Des macros et de goto !
Peu productif !
Structure de données
Bas niveau ! Interfaces riches
compactes et efficaces
Non sécurisée, dangereux !
C’est du C !
Un bon code
new / delete
Template meta-programming
Code dur à maintenir
le style C++ 11
Evolution du style C++
Le C++11 permet de faire du code Clean, Safe, Fast.
Clean & Safe : le nouveau style moderne
Fast : l’a toujours été
Aperçu des différences
Then
Now
return by value + move
circle* p = new circle( 42 );
vector<shape*> vw;
load_shapes( vw );
auto type deduction
+ auto again to deduce
vector<shared_ptr<shape
>>
delete p;
missing try/catch,
__try/__finally
new 
make_shared
auto p = make_shared<circle>( 42 );
auto vw = load_shapes();
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;
not exception-safe
}
T*  shared_ptr<T>
for( auto& s : vw ) {
range-for
if( s->weight() > 100 )
cout << *s << “ is a match\n”;
}
Pas de delete. Gestion
automatique du cycle de vie.
exception-safe
Gestion de la mémoire
Plus grosse « difficulté du C++ » : la gestion de mémoire
Il 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
“C++ is the best language for garbage collection principally
because it creates less garbage.”
Bjarne Stroustrup
Paroles d’experts !
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."
Caractéristiques de shared_ptr<T>
Un template C++ disponible dans <memory>
Basé sur le comptage de références
Gain de productivité & robustesse importants avec impact minimal sur les
perfs
Compatible avec les conteneurs STL
Compatible 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)
shared_ptr est Non-Intrusif
Possibilité d’instancier shared_ptr<T> sans modifier T
La gestion des références (uses/weaks) est dans le shared_ptr
Fonctionne avec les types prédéfinis: shared_ptr<int>
S’incorpore dans le code sans modifier les types existants
Un même type peut être manipulé parfois via un shared_ptr
et d’autres fois via d’autres mécanismes
make_shared<T>()
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
unique_ptr<T>
Une seule référence de l’objet
unique_ptr<Cat> c(new Cat);
unique_ptr<Cat> c2(Cat::Load(…));
Remplace auto_ptr, qui est obsolète
Compatible 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));
C++ 11 : Best-Of
Containers STL
vector<string> v;
v.push_back( “Geddy Lee” );
container par défaut: vector
compact, efficace, cache,
préfetch
array<string,50> a;
dictionary: map (arbre)
ou unordered_map
(hash)
map<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”;
vecteur de taillle fixe: array
compact, efficace, cache,
préfetch
unordered_multimap<string, string> phone;
phone[“Neil Peart”] = “+1 (416) 555-1212”;
phone[“Neil Peart”] = “+1 (905) 555-1234”;
Boucle for avec range
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
}
nullptr
nullptr exprime un pointeur nul
Ce n’est pas un int
class Foo {
public:
Foo(const char *s);
Foo(int n);
}
…
Foo f(NULL);
Foo f(nullptr);
NULL
Syntax Error de template<T>
La problème d’espace est résolu
list<vector<string>> lvs;
Une classe C++11 type
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.
enum & enum classclass enum
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
=default et =delete
Indiquer explicitement un opérateur de copie par défault
class Y {
// ...
Y& operator=(const Y&) = default;
Y(const Y&) = default;
}
// default copy semantics
Indiquer l’interdiction de la copie
class X {
// ...
X& operator=(const X&) = delete;
X(const X&) = delete;
};
// Disallow copying
constexpr
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 compilation
Attention
 constexpr ne remplace pas const (et vice versa)
decltype(E)
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
Initialisation des listes
Maintenant, on peut écrire cela
vector<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
Délégation de constructeur
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)} { }
// ...
};
Init. de membres de classes
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"};
std::string s{"Constructor run"};
};
// Cryptographic hash to be applied to all A instances
// String indicating state in object lifecycle
long long (64 bits)
Un type long mais qui est very long.
Au moins 64 bits
long long x = 9223372036854775807LL;
template typedef
Un typedef pour les templates
Permet une écriture plus élégante des templates dans le code
template<class T>
using Vec = std::vector<T,My_alloc<T>>;
Vec<int> fib = { 1, 2, 3, 5, 8, 13 };
// standard vector using my allocator
// allocates elements using My_alloc
Marche aussi avec le code style-C
typedef void (*PFD)(double);
using PF = void (*)(double);
// C style
// using plus C-style type
auto
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: pourquoi l’utiliser ?
auto utilise les règles de détection d’arguments des templates
 const auto * p = foo et const auto& r = bar compilent
auto...
 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
cbegin(), cend(), crbegin(), crend()
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
}
Références de RValue
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_shared
Les patterns de déplacement et de perfect forwarding sont simples à
mettre en oeuvre
Mais 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”
Efficacité du déplacement
set<widget> load_huge_data() {
set<widget> ret;
// … load data and populate ret …
return ret;
}
widgets = load_huge_data();
Efficace: pas de copie en
profondeur et pas besoin
du contournement
allocation dynamique +
retour de pointeur
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
(juste les
assignements de
pointeurs
Efficace, pas de copie
supplémentaire
Mécanique du Move / Value Types
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”;
:::
}
check (if appropriate)
};
move construction
move assignment
? Move: Also enable move
Copy 
if it can be cheaper than a deep copy.
Move 
/ Copy: Some non-value types
are naturally move-only. Example:
unique_ptr.
Nouveautés des algorithmes
<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)
Algorithmes : trois catégories
Parcours simples
 Exemple : for_each = le plus simple
Parcours avec transformations
 Exemple : copy = copie tous les éléments répondant à
une condition
Tris
 Exemples : sort, stable_sort, lower_bound
Parcours simples
All of
Any of
None of
For each
Find
Find end
Find first
Adjacent Find
Count
Mismatch
Equal
Is permutation
Search
Exemple : Find first
template<class InputIterator, class Predicate>
InputIterator find_if(InputIterator first,
InputIterator last,
Predicate pred);
Retourne le premier élément vérifiant le prédicat
Predicate :
 Fonctions prédéfinies
 Classe surchargeant operator()
 Lambda
Transformations
Copy
Move
Swap
Transform
Replace
Fill
Generate
Remove
Unique
Reverse
Rotate
Random shuffle
Partitions
Exemple Transform
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" ));
Tri et assimilés
Sort
Stable_sort
Partial_sort
Nth element
Binary search : lower_bound, upper_bound
Merge
Exemple : sort
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);
Lambdas
Fonctions simples
 pas paramétrables
Classes
 Lourdes à écrire
 Pb de localité
Lambdas
 Le meilleur des deux mondes
Le B.A. BA des lambdas
Les Lambda Expressions définissent et construisent des classes
fonctions anonymes
La Lamba Expression
for_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());
Compléments
Une lambda peut contenir plusieurs instructions
void par défaut
Lambda Stateless: [] signifie pas de capture du contexte
Capture-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

Initialisation des listes
Maintenant, on peut écrire cela
vector<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
Délégation de constructeur
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)} { }
// ...
};
Init. de membres de classes
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"};
std::string s{"Constructor run"};
};
// Cryptographic hash to be applied to all A instances
// String indicating state in object lifecycle
Chapitre 2
TESTS UNITAIRES DANS VISUAL STUDIO
Développement natif en C++ 11
Tests unitaires natifs
• 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/auth
oring-a-new-visual-studio-test-adapter.aspx
• Couverture de code
Tests unitaires natifs : Architecture
Programme (.exe)
Tests unitaires 1
(.dll)
Exécuteur de
tests (.exe)
Tests unitaires 2
(.dll)
Bibliothèque
1 (.lib)
Programme
Programme (.exe)
(.exe)
Bibliothèque
2
(.dll)
Chapitre 3
VISUAL C++11 ET NOV 2012 CTP
Développement natif en C++ 11
Visual C++ compiler Nov 2012 CTP
• 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…
Questions / Réponses
• N’oubliez pas : Le nouveau portail du C++ :
www.isocpp.org
The Space needle
Exemple de slide photo
Design
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">
Developpement
Exemple de graphe
•
Réseaux
Exemple
de Pie
chart
pour une
session
Réseaux
Développeurs
http://aka.ms/generation-app
http://aka.ms/evenements-
developpeurs
Les accélérateurs
Windows Azure, Windows Phone,
Windows 8
Pros de l’IT
Formez-vous en ligne
Retrouvez nos évènements
http://aka.ms/itcamps-france
Faites-vous accompagner
gratuitement
Essayer gratuitement nos
solutions IT
La Dev’Team sur MSDN
http://aka.ms/devteam
www.microsoftvirtualacademy.com
Retrouver nos experts
Microsoft
http://aka.ms/telechargements
L’IT Team sur TechNet
http://aka.ms/itteam