Nouvelles fonctionnalités de C ++ 11
- Le mot clé auto (C ++ 11) basé sur une plage pour la boucle (C ++ 11). Le pointeur nullptr (C ++ 11)
- Gestion dynamique de la mémoire C ++
- Tableau de conteneurs série forward_list;
- Héritage et polymorphisme: dérogation finale
- supprimer: ne pas générer la fonction membre par défaut
- default: force le compilateur à générer des fonctions membres par défaut
- Pointeurs intelligents: unique_ptr, shared_ptr, faible_ptr
- Conteneur associatif structuré par hachage: séries non ordonnées
Initialisation unifiée
La norme en C ++ 98 permet l'utilisation d'accolades {} pour définir une valeur initiale de liste uniforme pour les éléments du tableau
int array1[] = {1,2,3,4,5};
int array2[5] = {0};
Cela ne peut pas être initialisé pour les conteneurs vectoriels
vector<int> v{1,2,3,4,5};
Il ne peut pas être compilé, donc chaque fois que vous définissez un vecteur, vous devez d'abord le définir, puis utiliser une boucle pour lui attribuer une valeur initiale, ce qui est très gênant.
C ++ 11 étend la portée de la liste entre accolades (liste d'initialisation) pour la rendre disponible pour tous les types intégrés et les types définis par l'utilisateur. Lorsque vous utilisez la liste d'initialisation, vous pouvez ajouter un signe égal (=) Ne peut pas être ajouté .
Accolades de type intégré {} initialisation
// 内置类型变量
int x1 = { 10 };
int x2{ 10 };
int x3 = 1 + 2;
int x4 = { 1 + 2 };
int x5{ 1 + 2 };
int x6{ x1 + x2 };
// 数组
int arr1[5] {1, 2, 3, 4, 5};
int arr2[]{1, 2, 3, 4, 5};
// 动态数组,在C++98中不支持
int* arr3 = new int[5]{1, 2, 3, 4, 5};
// 标准容器
vector<int> v{ 1, 2, 3, 4, 5 };
map<int, int> m{ { 1, 1 }, { 2, 2, }, { 3, 3 }, { 4, 4 } };
Initialisation d'une liste de types personnalisée unique
class Point
{
public:
Point(int x = 0, int y = 0)
: _x(x), _y(y)
{}
private:
int _x;
int _y;
};
int main()
{
//两种初始化都可以
Point p{ 1, 2 };
Point p2(1, 2);
return 0;
}
Initialisation de plusieurs listes de types personnalisés
Si vous souhaitez prendre en charge l'initialisation de liste pour plusieurs objets, vous devez ajouter un constructeur avec un paramètre de type initializer_list à la classe (classe de modèle) . Remarque: initializer_list est un modèle de classe défini par le système. Il existe trois méthodes principales dans ce modèle de classe: l'itérateur begin (), end () et la méthode size () pour obtenir le nombre d'éléments dans l'intervalle.
template<class T>
class vector
{
public:
vector()
:_start(nullptr)
, _finish(nullptr)
, _endofstorage(nullptr)
{}
vector(initializer_list<T>l)
:_start(new T[l.size()])
{
_finish = _start;
for (auto e : l)
{
*_finish++ = e;
}
}
private:
T* _start;
T* _finish;
T* _endofstorage;
};
Déduction de type variable
dérivation automatique
déduction de type decltype
La condition préalable à l'utilisation de auto est: le type déclaré par auto doit être initialisé, sinon le compilateur ne peut pas dériver le type réel de auto
template<class T1,class T2>
//返回的时候,返回T1和T2都不行,应该返回T1+T2后的值的类型
auto Add(const T1& left, const T2& right)
{
return left + right;
}
Si le type réel du résultat après addition peut être utilisé comme type de retour de la fonction, il n'y aura pas d'erreur, mais cela nécessite que le programme s'exécute pour connaître le
type réel du résultat , c'est-à-dire RTTI (Run-Time Type Identification).
typeid
Peut uniquement afficher le type et ne pas définir le type avec sa classe de résultatdynamic_cast
Ne peut être utilisé que dans les systèmes d'héritage contenant des fonctions virtuelles
De nouveaux mots clés sont donc nécessaires
decltype est le type utilisé pour définir les variables en fonction du type réel de l'expression , par exemple: déduction du type de valeur de retour
//此处auto为占位符
//返回值类型追踪
auto Add( T1& left, T2& right)->decltype(left+right)
{
return left + right;
//ret = left + right;
}
int main()
{
int a = 1;
double b = 2.0;
cout<< Add(a, b);
return 0;
}
Gamme pour boucle
Gamme pour
dérogation finale
Résumée dans le polymorphisme
Pointeur intelligent
Résumé du pointeur intelligent
Nouveau tableau de conteneurs-tableau statique, liste_avant et séries non ordonnées
Constructeur délégué
Le soi-disant constructeur de délégation: fait référence à une méthode de construction de classe dans laquelle la fonction de délégation délègue la tâche construite au constructeur cible.
Le constructeur qui appelle la "version de base" dans la liste d'initialisation est appelé le constructeur délégué, et la "version de base" appelée est le constructeur cible.
Remarque: Le constructeur ne peut pas "déléguer" et utiliser la liste d'initialisation en même temps.
class Info {
public:
Info()
: _type(0)
, _name('a')
{
InitRSet();
}
Info(int type)
:Info()
//不能再在初始化列表中初始化其它的成员变量
//,_type(type)
{
//InitRSet();
_type = type;
}
Info(char type)
:Info()
{
//InitRSet();
_type = type;
}
private:
void InitRSet()
{
//初始化其他变量
}
private:
int _type;
char _name;
//...
};
- Le constructeur délégué peut également être le constructeur cible
- N'oubliez pas: la délégation en anneau peut toujours être compilée mais débordera sur la pile de droite
Référence de valeur
Contrôle de fonction par défaut
C ++ 11 permet aux programmeurs de contrôler si le compilateur doit générer les fonctions générées par défaut
Fonction par défaut explicite
En C ++ 11, vous pouvez ajouter = default à la définition ou à la déclaration de la fonction par défaut pour demander explicitement au compilateur de générer la version par défaut de la fonction . La =default
fonction modifiée est appelée fonction par défaut explicite .
class A
{
public:
A(int a): _a(a)
{}
// 显式缺省构造函数,由编译器生成
A() = default;
// 在类中声明,在类外定义时让编译器生成默认赋值运算符重载
A& operator=(const A& a);
private:
int _a;
};
A& A::operator=(const A& a) = default;
int main()
{
A a1(10);
A a2;
a2 = a1;
return 0;
}
Supprimer la fonction par défaut
Si vous souhaitez limiter la génération de certaines fonctions par défaut, en C ++ 98, la fonction est définie sur privé et non défini, de sorte que si quelqu'un d'autre veut l'appeler, une erreur sera signalée. En C ++ 11, c'est plus simple. Il suffit d'ajouter = supprimer à la déclaration de fonction. Cette syntaxe indique au compilateur de ne pas générer la version par défaut de la fonction correspondante. La fonction modifiée par = supprimer est appelée fonction de suppression .
class A
{
public:
A(int a): _a(a)
{}
// 禁止编译器生成默认的拷贝构造函数以及赋值运算符重载
A(const A&) = delete;
A& operator(const A&) = delete;
private:
int _a;
};
int main()
{
A a1(10);
// 编译失败,因为该类没有拷贝构造函数
//A a2(a1);
// 编译失败,因为该类没有赋值运算符重载
A a3(20);
a3 = a2;
return 0;
}
Remarque: Évitez d'utiliser la fonction de suppression avec explicite