Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

initialisation de tableau (juste curieux)

8 réponses
Avatar
Bruno Causse
bonjour,

j'aimerai connaitre la raison pourquoi un membre "tableau" ne peut etre
initialisé de facon static?

ex

class A {
.../...
unsigned char tab[4] = {NOMOVE, NOMOVE, NOMOVE, NOMOVE};
.../...
}

merci

8 réponses

Avatar
Fabien LE LEZ
On Tue, 16 Jan 2007 11:00:55 +0100, "Bruno Causse"
:

class A {
.../...
unsigned char tab[4] = {NOMOVE, NOMOVE, NOMOVE, NOMOVE};
.../...


Même s'il ne s'agit pas d'un tableau à la C, on ne peut pas
initialiser une variable membre ainsi.

class A
{
int n= 3; // Ne fonctionne pas !
};

En prime, un tableau à la C n'est pas vraiment une variable. C'est une
sorte de pointeur, avec un peu de sucre syntaxique pour en faciliter
l'initialisation.


Le code ci-dessous, par contre, fonctionne :

class A
{
public: A() : tableau (4, NOMOVE) {}
private: std::vector<char> tableau;
};

Avatar
Bruno Causse
"Fabien LE LEZ" a écrit dans le message de news:

On Tue, 16 Jan 2007 11:00:55 +0100, "Bruno Causse"
:

class A {
.../...
unsigned char tab[4] = {NOMOVE, NOMOVE, NOMOVE, NOMOVE};
.../...


Même s'il ne s'agit pas d'un tableau à la C, on ne peut pas
initialiser une variable membre ainsi.

class A
{
int n= 3; // Ne fonctionne pas !
};


oui tu as raison c'est la meme chose, mais ce n'est pas l'explication que
j'attendais :(

quel necanisme empeche que cela fonctionne ?

Le code ci-dessous, par contre, fonctionne :

class A
{
public: A() : tableau (4, NOMOVE) {}
private: std::vector<char> tableau;
};



oui c'est ce que je fais :)


Avatar
Fabien LE LEZ
On Tue, 16 Jan 2007 11:57:57 +0100, "Bruno Causse"
:

class A
{
int n= 3; // Ne fonctionne pas !
};


oui tu as raison c'est la meme chose, mais ce n'est pas l'explication que
j'attendais :(

quel necanisme empeche que cela fonctionne ?


Faut prendre le problème à l'envers : il n'y a aucun mécanisme qui
pourrait le faire fonctionner.

Il y a un certain nombre de mécanismes qui seraient agréables, mais
qui ne sont pas dans le standard.

Note que pour des types simples, on peut bricoler (cf code
ci-dessous).
Et les types moins simples ont généralement un constructeur par défaut
qui fait ce qu'il faut.




template <bool valeur_par_defaut> class Booleen
{
public:
Booleen (bool valeur_= valeur_par_defaut) : valeur (valeur_) {}

bool operator == (Booleen const& autre) const
{ return valeur == autre.valeur; }
bool operator == (bool const& autre) const
{ return valeur == autre; }
bool operator != (Booleen const& autre) const
{ return valeur != autre.valeur; }
bool operator != (bool const& autre) const
{ return valeur != autre; }

bool operator ! () const { return !valeur; }
operator bool() const { return valeur; }

Booleen& operator= (bool b) { valeur= b; return *this; }

private:
bool valeur;
};


class A
{
Booleen <false> x; // Sera initialisé à false automatiquement
};


Avatar
Jean-Marc Bourguet
Fabien LE LEZ writes:

En prime, un tableau à la C n'est pas vraiment une variable. C'est une
sorte de pointeur, avec un peu de sucre syntaxique pour en faciliter
l'initialisation.


Non. Les types tableaux ne sont pas tout a fait comme les autres parce
qu'il y a une conversion implicite en un pointeur vers le premier element,
mais cette conversion implicite n'en fait pas des pointeurs. C'est parfois
trompeur mais reflechir en terme de pointeur pose beaucoup de probleme --
sizeof, effet de &, sans aborder les templates qui ont leur propres
particularite avec la gestion des tableaux.

(Et cette conversion est active pour n'importe quel objet, qu'il soit nomme
-- auquel cas c'est une variable -- ou non).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Jean-Marc Bourguet
"Bruno Causse" writes:

oui tu as raison c'est la meme chose, mais ce n'est pas l'explication que
j'attendais :(

quel necanisme empeche que cela fonctionne ?


Je ne comprends pas tellement la question. Avant de demander pourquoi ca
ne fonctionne pas, il faudrait peut-etre definir ce que ca devrait faire
pour que tu consideres que ca fonctionne.

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
James Kanze
Fabien LE LEZ wrote:
On Tue, 16 Jan 2007 11:00:55 +0100, "Bruno Causse"
:

class A {
.../...
unsigned char tab[4] = {NOMOVE, NOMOVE, NOMOVE, NOMOVE};
.../...


Même s'il ne s'agit pas d'un tableau à la C, on ne peut pas
initialiser une variable membre ainsi.

class A
{
int n= 3; // Ne fonctionne pas !
};


Peut-être parce que l'élément n'existe qu'à partir du moment
qu'on en crée une instance.

De l'autre côté, si la classe est un aggloméré, on peut bien
écrire :

struct A
{
int n ;
unsigned char tab[ 4 ] ;
} ;
A unA = { 3, { NOMOVE, NOMOVE, NOMOVE, NOMOVE } } ;

Ce genre d'astuce peut servir pour faciliter l'initialisation
des types plus complexes :

class A
{
public:
A() ;
// ...

private:
struct Data { int n ; unsigned char tab[ 4 ] ; }
myData ;
static Data ourInitValues ;
} ;

Puis :

A::Data ourInitValues = { 3, { NOMOVE, NOMOVE, NOMOVE, NOMOVE } } ;

A::A()
: myData( ourInitValues )
{
}

En prime, un tableau à la C n'est pas vraiment une variable. C'est une
sorte de pointeur, avec un peu de sucre syntaxique pour en faciliter
l'initialisation.


Pas du tout. Un tableau à la C, c'est bien un tableau, et ce
n'est en aucun cas un pointeur. Mais c'est un type deuxième
classe, sans constructeur de copie ni opérateur d'affectation
par défaut. Et une conversion inattendue, pour dire le moindre.

Boost::array resoud la problème de la conversion et les
opérateurs qui manque. On revanche, il pose toujours le problème
d'initialisation dans une liste d'initialisation d'un
constructeur. (Mais un truc comme je viens de montrer doit
marcher, sans qu'il y ait besoin de la struct wrapper.)

Le code ci-dessous, par contre, fonctionne :

class A
{
public: A() : tableau (4, NOMOVE) {}
private: std::vector<char> tableau;
};


Oui, mais s'il y a beaucoup d'instances, c'est vraiment coûteux
pour un tableau de quatres octets.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Bruno Causse
"James Kanze" a écrit dans le message de news:


class A
{
public: A() : tableau (4, NOMOVE) {}
private: std::vector<char> tableau;
};


Oui, mais s'il y a beaucoup d'instances, c'est vraiment coûteux
pour un tableau de quatres octets.



2*2^24 instances :-)


Avatar
James Kanze
Bruno Causse wrote:
"James Kanze" a écrit dans le message de news:


class A
{
public: A() : tableau (4, NOMOVE) {}
private: std::vector<char> tableau;
};


Oui, mais s'il y a beaucoup d'instances, c'est vraiment coûteux
pour un tableau de quatres octets.


2*2^24 instances :-)


Aï. Je ne crois pas que std::vector y convient, alors. En tant
que tableau de type C, ton tableau occupe 4 octets. En tant que
vector, il occupe typiquement 12 (trois pointeurs), plus les
données et ce qu'il faut ajouter pour la gestion de la mémoire
dynamique -- sur mon système, quelque chose comme 16 octets. Du
coup, on multiplie l'utilisation de la mémoire par 7, avec
l'effet qu'on imagine sur la localité (ce qui risque de jouer
un rôle important, parce que autant d'instances ne tiendront
jamais en cache).

Essaie une des solutions que j'ai proposées. Ou peut-être même
mieux, une classe simple sur mesure :

class Moves
{
public:
Moves()
{
std::uninitialized_fill_n( data, 4, NOMOVE ) ;
}
unsigned char& operator[]( size_t i )
{
return data[ i ] ;
}
unsigned char const&operator[]( size_t i ) const
{
return data[ i ] ;
}
private:
unsigned char data[ 4 ] ;
} ;

(Voire avec n'importe quelle autre solution pour
l'initialisation. L'avantage de l'emballer comme ça, c'est que
tu peux expérimenter facilement avec de différentes solutions,
au cas où il y a un problème de performance.)

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34