OVH Cloud OVH Cloud

Définir un type avec valeurs manquantes. Comment faire ?

22 réponses
Avatar
Marc
Bonjour,
je cherche à introduire la notion de valeur manquante pour des objets.
Je me suis dit que les patrons de classe pouvaient être la solution avec une
implémentation du genre :

template <class T >
class CTypeBase {

public :

CTypeBase() : FMissingValue(true),FValue(T()) {}
CTypeBase(const T &x) : FMissingValue(false),FValue(x) {}

bool IsMissingValue(void) const { return FMissingValue;}
void SetMissingValue(void) { FMissingValue=true;}

T GetValue(void) const { return FValue;}
void SetValue(T _value) { FMissingValue=false;FValue=_value;}

// redéfinition des opérateurs dans mon cas ...
// opération avec missing -> missing

private :

bool FMissingValue;
T FValue;

};

typedef CTypeBase<int> CTypeInt;

Ma question :
Pour des gros objets, ça peut convenir, mais pour des int/double/etc, ça
paraît très peu performant !
Surtout si je veux lire/écrire des données sur disque...
Est-ce que quelq'un connaît une solution à ce problème ?

Merci

10 réponses

1 2 3
Avatar
Falk Tannhäuser
Marc wrote:
Il y a des chances pour que sizeof(bool) == sizeof(int)



désolé,
mais chez moi (Windows + compilateur C++Builder 6),
sizeof(bool) donne 1
et sizeof(int) donne 4


Et si tu as
struct int_and_bool { int i; bool b; };
alors qu'est-ce qu'il donne
sizeof(int_and_bool)
?

Falk


Avatar
Marc
Et si tu as
struct int_and_bool { int i; bool b; };
alors qu'est-ce qu'il donne
sizeof(int_and_bool)
?

Et bien ça me donne 8 !
mieux :
int_and_bool x;
sizeof(x.b) me donne 1
Où est le reste !?

je suppose que ce serait la même chose avec une classe...
Marc
Avatar
Jean-Marc Bourguet
"Marc" writes:

Et si tu as
struct int_and_bool { int i; bool b; };
alors qu'est-ce qu'il donne
sizeof(int_and_bool)
?

Et bien ça me donne 8 !


Le contraire m'aurait tres fortement etonne.

mieux :
int_and_bool x;
sizeof(x.b) me donne 1


Heureusement.

Où est le reste !?


Padding pour respecter les contraintes d'alignement.

je suppose que ce serait la même chose avec une classe...


Oui.

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
Fabien LE LEZ
On 19 Oct 2004 00:18:05 -0700, :

Comme a dit Fabien, tant qu'il n'y a pas de preuve que c'est un
problème, un bool en plus est la solution universellement admis. Même is
parfois il fait doubler la taille de l'objet.


Du moins, en RAM. Il peut en aller autrement sur le disque dur.


--
;-)

Avatar
Fabien LE LEZ
On Tue, 19 Oct 2004 09:25:21 +0200, "Marc" :

Vaut-il mieux stocker l'information sur une valeur manquante dans un int (4
octets) avec les valeurs 0 ou 1 que dans un bool ?


A priori, le bool est plus explicite, donc il faut le favoriser. Si
les mesures montrent que mettre un int à la place est une réelle
optimisation, alors seulement on peut admettre cette solution.


--
;-)

Avatar
adebaene
"Marc" wrote in message news:<4174c19a$0$20574$...

merci,
c'est justement une question que je me posais.
Vaut-il mieux stocker l'information sur une valeur manquante dans un int (4
octets) avec les valeurs 0 ou 1 que dans un bool ? C'est plus rapide en
lecture/écriture sur disque et traitement en mémoire ?


Etant donné que int est le type "naturel" du processeur, il y a des
chances que int soit le plus rapide. Mais franchement, la différnece
sera négligeable. Commences par faire un programme propre et clair (ce
qui veut dire dans ton cas utilises bool : le type "naturel" par
rapport à la sémantique de ton programme). Tu te poseras des questions
capilotractées sur ce niveau de détails d'optimisation si le besoin
sans fait sentir, et je suis prêt à parier que dans le cas présent, ce
ne sera pas le cas.

De toute façon, comme tu l'as remarqué dans un autre message, que tu
fasses :
struct A
{
int valeur;
bool valid;
};

ou bien
struct B
{
int valeur;
int valid;
};

Dans les 2 cas, sur des machines "courantes" (càd des PC en 32 bits
avec un compilo décent), la structure fait 8 octets pour des raisons
d'optimisation des accès mémoires (alignement). Ton compilateur se
chargeant très bien de ces détails tout seul, tu peux les oublier dans
un 1er temps.

Arnaud

Avatar
adebaene
"Marc" wrote in message news:<4173ad80$0$8960$...
Bonjour,
je cherche à introduire la notion de valeur manquante pour des objets.


Pour quoi faire ? Quelles opérations permises sur ces objets ?


par exemple :
CTypeInt x,
y; // valeur manquante
CtypeInt z=x+y; // doit me donner valeur manquante or avec le type int
standart, il y a toujours une valeur !


Avant de te poser des questions d'optimisation, résouds ce problème
là, qui est un problème de conception beaucoup plus sérieux que les
détails bool contre int ,alignement des structures et tutti-quanti.

Le problème, c'est que tes redéfinitions d'opérateur ne tiennent de
toute évidence pas compte de l'état de FMissingValue et utilisent
toujours FValue sans se poser de questions. Plusieurs solutions sont
envisageables, selon la sémantique souhaitée. J'en vois au moins 2
évidentes:
- une opération impliquant au moins un CTypeBase avec
FMissingValue==true lève une exception.
- une opération impliquant au moins un CTypeBase avec
FMissingValue==true renvoie toujours un CTypeBase avec
FMissingValue==true.

Arnaud



Avatar
Matthieu Moy
Fabien LE LEZ writes:

C'est dangereux (Y'a longtemps, certains avaient choisi "9/9/99" comme
date "bidon"... sans penser que le 9 septembre 1999 finirait par
arriver ;-) ),


Sauf erreur de ma part, la réalité est plutôt « Y'a longtemps,
certains avaient choisi à raison 99/99/99 comme date bidon. Un peu
avant le 9 septembre 1999, quelques journalistes se sont dit que ça
pourrait faire un Y2K bug remixé et qu'il y avait peut-être un bon
filon si on disait que peut-être quelqu'un avait mis 9/9/99 à la
place » ;-)

Enfin, c'est ce que m'a dit quelqu'un qui était « responsable du bug
du 9 semptembre » dans sa boite ...

--
Matthieu

Avatar
Fabien LE LEZ
On Tue, 19 Oct 2004 21:19:12 +0200, Matthieu Moy
:

Un peu
avant le 9 septembre 1999, quelques journalistes se sont dit que ça
pourrait faire un Y2K bug remixé et qu'il y avait peut-être un bon
filon si on disait que peut-être quelqu'un avait mis 9/9/99 à la
place » ;-)


A l'époque, je lisais encore quelques journaux. Manifestement, j'ai
bien fait d'arrêter...


--
;-)

Avatar
kanze
Fabien LE LEZ wrote in message
news:...
On 19 Oct 2004 00:18:05 -0700, :

Comme a dit Fabien, tant qu'il n'y a pas de preuve que c'est un
problème, un bool en plus est la solution universellement admis. Même
is parfois il fait doubler la taille de l'objet.


Du moins, en RAM. Il peut en aller autrement sur le disque dur.


Tout à fait. Mais il ajoute toujours au moins un octet.

Si on sait que les valeurs vont être très petites, on peut en économiser
pas mal de la mémoire. Dans une base de données, par exemple, il serait
tout à fait raisonable d'utiliser un signed char pour le nombre
d'enfants (avec éventuellement -1 comme valeur spéciale signifiante non
renseigné). Dans certains cas, de telles optimisations valent la peine.

Mais de telles optimisations ne sont disponibles que dans les cas
précis. Elles ne représentent pas une possibilité d'optimisation
générale.

Reste que dans le cas général, si j'avais à enrégistrer le nombre
d'enfants, je déclarerais int, et s'il y avait la possibilité que le
nombre ne soit pas renseigné, Fallible<int>. Si je savais d'avance que
j'allais avoir à faire avec des millions d'enrégistrements, en revanche,
c'est probable que je passerais à signed char dès la conception.

Note que si on n'a pas besoin de toute la portée d'un entier, on peut
toujours y mettre un bool de plus, sans utiliser plus de la mémoire. Si
les valeurs à enrégistrer sont tous non-négatives, on déclare le type
signé, et on se sert de -1 comme valeur singulière. Sinon, on peut y
arriver à coups de masquage, mais là, il faudrait vraiment être
déséspéré ; c'est beaucoup moins transparent, et typiquement, beaucoup
moins rapide à l'execution aussi.

Et si on est vraiment serré en mémoire, on peut packer encore plus. Un
champs qui ne peut prendre que des valeurs 0...3 peut se mettre sur 2
bits. Note que c'est ce qui se fait dans std::ios, avec par exemple
ios::adjustfield, ios::floatfield, etc. Dans ce cas-là, sans doute pour
des raisons historiques -- j'ai du mal à imaginer une situation où les
peu d'octets gagnés puissent faire une différence.

--
James Kanze GABI Software http://www.gabi-soft.fr
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


1 2 3