OVH Cloud OVH Cloud

Classe Matrix de Stroustrup

5 réponses
Avatar
Boris Sargos
Bonjour,

Dans son livre, Stroustrup propose un implémentation d'une classe Matrix,
avec comme conteneur un valarray. Jusque-là ok.
Mais, il déclare un pointeur sur ce valarray :

class Matrix {
valarray<double>* v;
/* ... */
}

C'est toujours pénible de devoir écrire (*v) au lieu de v dès que l'on
souhaite accéder aux éléments de la matrice. Comme a priori, la classe
valarray n'a pas besoin d'être dérivée (je ne vois pas l'intérêt de la
polymorphie sur le valarray pour une classe Matrix), je ne comprends pas son
choix. Pourquoi déclarer un valarray* au lieu d'un valarray ?

Merci de votre réponse.

5 réponses

Avatar
Ivan Vecerina
"Boris Sargos" wrote in message
news:c6tfbk$p1r$
Dans son livre, Stroustrup propose un implémentation d'une classe Matrix,
avec comme conteneur un valarray. Jusque-là ok.
Mais, il déclare un pointeur sur ce valarray :

class Matrix {
valarray<double>* v;
/* ... */
}

C'est toujours pénible de devoir écrire (*v) au lieu de v dès que l'on
souhaite accéder aux éléments de la matrice. Comme a priori, la classe
valarray n'a pas besoin d'être dérivée (je ne vois pas l'intérêt de la
polymorphie sur le valarray pour une classe Matrix), je ne comprends pas
son

choix. Pourquoi déclarer un valarray* au lieu d'un valarray ?


Certaines opérations, pourraient bénéficier du fait que v est un pointeur
( p.ex. pour transférer le contenu d'une matrice à une autre lorsque
la matrice source est temporaire).
Mais rien dans le code qui suit ne requière l'usage d'un pointeur.

L'auteur semble ne pas aller ici assez profondément dans les détails
d'une implémentation pour qu'un quelquonque bénéfice devienne apparent.


Soit dit en passant, std::valarray est loin d'être un type populaire.
Il fut intégré au standard pour permettre en théorie des optimisations
spécifiques sur certains compilateurs, mais c'est resté un voeu pieux.

Si une performance optimale est nécessaire, des librairies beaucoup plus
complètes telles que Blitz++ sont disponible (et non-basées sur valarray)
(http://www.oonumerics.org/blitz/).


Salutations,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Brainbench MVP for C++ <> http://www.brainbench.com

Avatar
Boris Sargos
Salut Ivan, merci pour ta réponse.

Certaines opérations, pourraient bénéficier du fait que v est un pointeur
( p.ex. pour transférer le contenu d'une matrice à une autre lorsque
la matrice source est temporaire).


Pourquoi pour cette opération un pointeur est-il plus judicieux ? Là je ne
saisis pas.

Mais rien dans le code qui suit ne requière l'usage d'un pointeur.
L'auteur semble ne pas aller ici assez profondément dans les détails
d'une implémentation pour qu'un quelquonque bénéfice devienne apparent.


Je me demande si d'une manière générale, déclarer un objet membre ne permet
pas tout simplement de l'initialiser au moment opportun. Après une longue
réflexion, j'ai compris que lorsque l'on déclare un objet (un valarray par
exemple), celui-ci s'initialise avec les valeurs par défaut. Et c'est
seulement dans le constructeur de l'objet Matrix que celui est initialisé
correctement. Le déclarer en pointeur permet donc un très léger gain de
temps. Qu'en penses-tu ?


Soit dit en passant, std::valarray est loin d'être un type populaire.
Il fut intégré au standard pour permettre en théorie des optimisations
spécifiques sur certains compilateurs, mais c'est resté un voeu pieux.


Par ailleurs, ce que tu dis sur le valarry m'intéresse. C'est vrai que peu
de gens l'utilise. J'ai écrit ma classe Matrix avec valarray, slice et
slice_iter pensant que ce serait vraiment plus rapide. Mais je suis très
gêné par ce conteneur qui ne fournit pas d'itérateur. Je pense que je vais
basculer vers vector. As-tu une opinion là-dessus ?


Merci pour tes conseils.

Boris.







Salutations,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Brainbench MVP for C++ <> http://www.brainbench.com




Avatar
Richard Delorme
Bonjour,

Dans son livre, Stroustrup propose un implémentation d'une classe Matrix,
avec comme conteneur un valarray. Jusque-là ok.
Mais, il déclare un pointeur sur ce valarray :

class Matrix {
valarray<double>* v;
/* ... */
}

C'est toujours pénible de devoir écrire (*v) au lieu de v dès que l'on
souhaite accéder aux éléments de la matrice. Comme a priori, la classe
valarray n'a pas besoin d'être dérivée (je ne vois pas l'intérêt de la
polymorphie sur le valarray pour une classe Matrix), je ne comprends pas son
choix. Pourquoi déclarer un valarray* au lieu d'un valarray ?


A mon avis, ce n'est qu'un exemple d'une façon possible possible de
faire, qui illustre la manipulation d'un pointeur. Je ne crois pas qu'il
faut y rechercher une quelconque optimisation d'écriture ou de code
finalement produit. La version d'une classe Matrix avec valarray sans
pointeur est d'ailleurs donné en exercice à la fin de ce chapître.

--
Richard

Avatar
Gabriel Dos Reis
"Boris Sargos" writes:

[...]

| > Soit dit en passant, std::valarray est loin d'être un type populaire.
| > Il fut intégré au standard pour permettre en théorie des optimisations
| > spécifiques sur certains compilateurs, mais c'est resté un voeu pieux.
|
| Par ailleurs, ce que tu dis sur le valarry m'intéresse. C'est vrai que peu
| de gens l'utilise.

Et peu de gens font du calcul numérique aussi.
Il y a tableau et tableau, il y a calcul numérique et caclcul
numérique. Je doute qu'un seul type de tableau arrivera à satisfaire
tout le monde. Valarray convient à un certain type de calcul numérique
sur les tableaux.

| J'ai écrit ma classe Matrix avec valarray, slice et
| slice_iter pensant que ce serait vraiment plus rapide. Mais je suis très
| gêné par ce conteneur qui ne fournit pas d'itérateur. Je pense que je vais
| basculer vers vector. As-tu une opinion là-dessus ?

Les itérateurs c'est bien quand c'est ce qu'il faut.
Si on veut faire du BLAS *et* on veut avoir une performance proche de
Fortran, utiliser les itérateurs et n'est pas vraiment ce que je
choisirai. Les itérateurs « détruisent » la structure d'une structure
de donnée et les relations entre un élément et son contenant. En
particulier si je voulais retenir le fait que deux tableaux ne
« s'aliasent » pas, les itérateurs sont les dernières choses que je
prendraient en ce sens qu'ils ne savent rien et véhiculent
pratiquement aucune information, en particulier le compilateur n'en
tirera pas grand choses.

-- Gaby
Avatar
Gabriel Dos Reis
"Boris Sargos" writes:

| Bonjour,
|
| Dans son livre, Stroustrup propose un implémentation d'une classe Matrix,
| avec comme conteneur un valarray. Jusque-là ok.
| Mais, il déclare un pointeur sur ce valarray :
|
| class Matrix {
| valarray<double>* v;
| /* ... */
| }
|
| C'est toujours pénible de devoir écrire (*v) au lieu de v dès que l'on
| souhaite accéder aux éléments de la matrice. Comme a priori, la classe
| valarray n'a pas besoin d'être dérivée (je ne vois pas l'intérêt de la
| polymorphie sur le valarray pour une classe Matrix), je ne comprends pas son
| choix. Pourquoi déclarer un valarray* au lieu d'un valarray ?

L'auteur voulait en fait déclarer un valarray<>. Ce qui est apparu
dans le livre est probablement un lapsus en passant aux éléments de la
matrice comme se trouvant en « free store ». Il est probable que ce
point sera revu dans les prochaines versions.

-- Gaby