Je suis nouveau avec C ++ et j'ai rencontré ce problème. Voici mon code:
class A { std::vector <int> vec = std::vector<int>(10); };
Cela me donne une erreur en disant s'attend à un spécificateur de type
. Je sais que cette façon d'initialiser un vecteur n'est pas acceptable et qu'elle devrait être effectuée dans le constructeur mais je suis curieux de savoir pourquoi cela échoue. J'ai également remarqué que ceci:
class A { std::vector <int> vec(10); };
Fonctionne parfaitement bien.
Ma question est donc de savoir pourquoi le deuxième cas fonctionne même si nous sommes toujours en train de créer des vecteurs avec " taille prédéfinie "( std :: vector
), et pourquoi le premier cas échoue-t-il? merci.
P.S
J'essaie de créer un vecteur avec une taille de 10 pouces, pas de créer un vecteur avec 10
déjà inséré dedans.
3 Réponses :
Depuis C ++ 11, nous avons initialiseurs de membres de données non statiques , rendant cette approche d'initialisation des membres totalement valide. Cependant, vous devez utiliser soit Formellement, si un initialiseur est présent ici, il doit être a > avec une accolade-or-equal -initializer production grammaticale. Puisque vous avez utilisé à la place une syntaxe qui ne compte pas comme une initialisation ici, le compilateur essaie de faire une déclaration de fonction à partir de Le chapitre intitulé "Problème 1" dans la proposition de fonctionnalité d'origine ( N2756 ) explique que L'auteur y note que le comité aurait pu le laisser faire, et le faire fonctionner comme d'autres déclarations - c'est-à-dire que c'est une fonction si cela peut être, et un objet sinon *. Mais l'auteur a décidé d'aller dans une direction différente et d'interdire simplement la syntaxe pour éviter le problème dans ce cas particulier. Malheureusement, cela rend les initialiseurs de la forme “( liste-d'expressions )” ambigus au moment où la déclaration est analysée [..] < / em> Une solution possible est de s'appuyer sur la règle existante selon laquelle, si une déclaration peut être un objet ou une fonction, alors c'est une fonction [..] p>
Une solution similaire serait d’appliquer une autre règle existante, actuellement utilisée uniquement dans les modèles, selon laquelle si Ces deux solutions introduisent des subtilités susceptibles d'être mal comprises par de nombreux utilisateurs (comme en témoignent les nombreuses questions sur comp.lang.c ++ sur la raison pour laquelle " La solution proposée dans cet article est de n'autoriser que les initialiseurs des formes «= clause d'initialisation » et «{ liste-d'initialisation }». / strong> Cela résout le problème d'ambiguïté dans la plupart des cas. Telle est la vie. J'essaie de créer un vecteur avec une taille de 10 pouces, pas de créer un vecteur avec 10 déjà insérés. C'est un point important. Attention, car l'initialisation d'un vecteur avec Vous devez donc utiliser soit la syntaxe * C'est là que l'analyse la plus vexante peut parfois vous mordre. toutes les occurrences de déclarations de fonctions involontaires ne sont pas un exemple de l'analyse la plus vexante. =
, soit {}
.
vec
, ce qui casse car 20
n'est pas un type.
Pourquoi?
()
n'a pas été autorisé ici pour éviter une certaine confusion en ce qui concerne les déclarations des fonctions membres.
T
pouvait être un type ou autre chose, alors c’était autre chose; et nous pouvons utiliser « typename
» si nous entendons vraiment un type [.. int i (); < / code> »à la portée du bloc ne déclare pas un
int
initialisé par défaut.
Et alors?
{}
a gagné " t fais ça . L'initialisation "uniforme" malheureusement a simplement ajouté plus de significations . Voilà pour résoudre le problème d'ambiguïté… =
, soit simplement le faire dans le constructeur (mon préféré).
Merci pour l'explication détaillée :)
@ user3503143 De rien! Je ne savais pas cela, alors j'ai appris quelque chose aussi.
Ce n'est pas bien écrit. Vous pouvez également utiliser l'exemple suivant. Ici, je vais laisser le vecteur vide, mais reserve ()
de l'espace pour 20 pointeurs, donc vous pouvez insérer sans avoir à réallouer. Une solution plus simple et meilleure (avec un constructeur) serait:
A.cpp
Setting size
A.hpp
#include "A.hpp" int main() { A a; }
main.cpp
#ifndef A_HPP #define A_HPP_ #include <iostream> #include <vector> class A { public: A(); ~A(); std::vector<int> vec; }; #endif /* !A_HPP_ */
Output:
#include "A.hpp" A::A() { this->vec.reserve(20); std::cout << "Setting size" << std::endl; } A::~A() { }
Et votre taille de vecteur est faite.
Ce n'est pas au mauvais endroit, et c'est permis, c'est juste écrit de manière invalide.
Vous n'êtes pas autorisé à déclarer et à initialiser une variable membre avec la syntaxe type name (value);
, mais vous pouvez avec type name {value};
ou type name = value;
.
Voici la syntaxe du Standard:
[class.memedral/1
class C { int a = 0; int b{0}; }
Et
[dcl.init /1
brace-or-equal-initializer: = initializer-clause braced-init-list braced-init-list: { initializer-list , (opt) } { designated-initializer-list , (opt) } { }
Donc, ce qui suit:
member-declaration: attribute-specifier-seq(opt) decl-specifier-seq(opt) member-declarator-list(opt); [...] member-declarator-list: member-declarator member-declarator-list , member-declarator member-declarator: [...] declarator brace-or-equal-initializer(opt) [...]
est valide.
La définition de C :: a
est une déclaration-membre avec une liste-déclarateur-membre composée d'un seul membre initialisé avec un initialiseur-accolade du form = clause d'initialisation
.
De même, C :: b
utilise la forme braced-init-list .
D'un autre côté, vous ne trouverez aucune syntaxe pour int c (0);
.
En effet, le premier extrait de code déclare une fonction appelée. Je suppose que c'est le double, mais il y a peut-être mieux: Ma tentative d'initialisation de valeur est interprétée comme une déclaration de fonction, et pourquoi pas A a (()); le résoudre?
vec
, qui renvoiestd::vector
et prend un paramètre deC ++ 11 ou supérieur? utilisez
{20}
au lieu de(20)
. Vous avez déclaré une fonction qui prend une erreur de syntaxe et renvoie unstd::vector
.Merci pour votre réponse. J'essayais de créer un vecteur avec de la mémoire allouée pour 6 membres, est-ce que
{20}
fera de même?Ce n'est pas une erreur d'analyse des plus vexantes. Il s'agit d'une définition variable, mais dans un endroit, elle n'est pas autorisée.
@mch Pour
vector
, car il a un constructeur initializer_list donc ils ne sont pas les mêmes.vector (20)
: 20 éléments avec une valeur de 0.vector {20}
: un seul élément avec une valeur de 20.@Yksisarvinen Non, ce n'est pas le cas. Une déclaration de fonction ne peut pas avoir de littéral entier à la place de sa liste d'arguments.