Constructeur par défaut d'un std::array

Constructeur par défaut d'un std::array - C++ - Programmation

Marsh Posté le 18-08-2013 à 05:55:01    

Bonjour.
 
Question bête: est-ce que le constructeur par défaut d'un

Code :
  1. std::array<T, N>

initialise tout le contenu par défaut.  
 
En C, utiliser :

Code :
  1. T x[N];

est dangereux si on l'utilise directement car les valeurs ne sont pas initialisées.
 
Mais en C++, lorsque je fais :

Code :
  1. std::array<T, N> x;

est-ce que j'ai la garantie que le constructeur par défaut de chaque élément a été appelé ?
 
Je pose la question parce que sur cppreference, il est dit que :

Code :
  1. (constructor) (implicitly declared) (public member function)
  2. default-constructs or copy-constructs every element of the array

ce qui est plutôt rassurant.  
 
Mais je me méfie car je ne vois pas où cela apparait dans le standard.
 
Alors qu'en est-il réellement ?
 
Merci beaucoup  :jap: .

Message cité 1 fois
Message édité par I_have_a_big_problem le 18-08-2013 à 05:55:26
Reply

Marsh Posté le 18-08-2013 à 05:55:01   

Reply

Marsh Posté le 18-08-2013 à 09:56:39    

Bonjour !
 
Pour l'appel au constructeur, vous n'êtes sûr que du fait que le constructeur par défaut de la classe std::array est appelé, c'est celui-ci qui doit normalement se charger du reste.
 
Jusqu'ici, je n'ai jamais eu de soucis de ce genre avec la STL, donc on peut a priori supposer que tout est bien initialisé.
 
Au pire, si vous êtes motivé (car le code n'est pas super lisible, il faut bien le reconnaître ... :( ), vu que c'est un template, vous avez le code dans le fichier de déclaration, vous pouvez vous y plonger pour trouver (ou pas, ou après une plongée en apnée dans pas mal de classe ... :) ) votre réponse !
 
Sinon, vous faites un petit rapidement sample et laissez valgrind détecter pour vous les problèmes d'initialisation de mémoire.
 
Bonne continuation !


Message édité par Farian le 18-08-2013 à 10:07:51
Reply

Marsh Posté le 18-08-2013 à 14:40:38    

I_have_a_big_problem a écrit :

Mais je me méfie car je ne vois pas où cela apparait dans le standard.


 
Pourtant, le paragraphe 23.2.1 parait plutôt clair dans son troisième point.
Cela dit, attention aux types primitifs : un entier ne sera pas automatiquement initialisé et une valeur par défaut dépend en général du contexte.
 


---------------
last.fm
Reply

Marsh Posté le 18-08-2013 à 16:23:17    

Apres lectures des sources, la classe boost::array (je suppose que la version de ton compilateur doit beaucoup y ressembler) ne définit même pas de constructeur par Default.
en gros ca signifie que le compilateur appellera le constructeur par default sur tous les attributs (ici, l'array). Bref, si tu utilise un array de "classes" les constructeurs par Default seront appelés, si tu es sur des types natifs, tu n'as aucunes garanties.
 
si tu veux une initialisation optimisée, tu peux utiliser un truc du style.
 std::memset(array.data()x, 0, sizeof(array));
 
 

Reply

Marsh Posté le 18-08-2013 à 16:48:23    

vhb__ a écrit :

Apres lectures des sources, la classe boost::array (je suppose que la version de ton compilateur doit beaucoup y ressembler) ne définit même pas de constructeur par Default.
en gros ca signifie que le compilateur appellera le constructeur par default sur tous les attributs (ici, l'array). Bref, si tu utilise un array de "classes" les constructeurs par Default seront appelés, si tu es sur des types natifs, tu n'as aucunes garanties.
 
si tu veux une initialisation optimisée, tu peux utiliser un truc du style.
 std::memset(array.data()x, 0, sizeof(array));
 
 


 
Oh le beau bug qui va n'initialiser qu'une partie des données ... bien joué ! [:kunks]  
 
Au lieu de faire ce genre "d'optimisation" qui s'appuie sur des interfaces antédiluviennes et douteuses, mieux vaut se contenter de faire la version simple et itérer pour initialiser (et dans C++11, on ne manque pas de façons élégantes de le faire)


---------------
last.fm
Reply

Marsh Posté le 18-08-2013 à 17:14:57    

Je ne pense pas.

 

Si je me souviens bien, le standard garantie quelque chose du style

 
Code :
  1. sizeof(std::array<T, N> ) == sizeof(T[N])
 

(EDIT: Typo)

Message cité 1 fois
Message édité par vhb__ le 18-08-2013 à 17:37:17
Reply

Marsh Posté le 18-08-2013 à 17:48:56    

vhb__ a écrit :

Je ne pense pas.
 
Si je me souviens bien, le standard garantie quelque chose du style  
 

Code :
  1. sizeof(std::array<T, N> ) == sizeof(T[N])


 
(EDIT: Typo)


 
 
Hmm ... Je n'ai pas vu de telle garantie, mais le standard montre une portion d'implémentation d'Array qui va dans ce sens ...
Pour en revenir au remplisage, vu que je viens d'y jeter un oeil, Array propose une méthode void fill( const T& ); qui semble tout à fait appropriée pour une initialisation.


---------------
last.fm
Reply

Marsh Posté le 18-08-2013 à 18:03:09    

effectivement, elle m’était passée sous les yeux. Tu as raison, c'est clairement plus propre.

Reply

Marsh Posté le 19-08-2013 à 08:40:15    

Les memset ca fait toujours son effet avec des objets avec interface abstraites :o
 
http://codepad.org/orcEaJFj

Reply

Marsh Posté le 20-08-2013 à 22:37:28    

c'est pas faux, null comme pointeur de vtable c'est une mauvaise idée.
 
(d’ailleurs, même sans la virtuelle pure, juste avec le dtor virtual, ça devrait péter aussi)
 
Mais la, on parlait de types natifs. Sinon, le constructeur par default est appelé. Donc, pas de problème.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed