peut-on être sûr que les entiers x et y se suivent en mémoire,quelque soit le compileur ? ( a-t-on *(&(A.x)+1) = A.y ?)
Surement pas, vu que c'était déjà faux en C avec les structs. En C, on était sur d'avoir x avant y mais il peux y avoir un 'trou' entre (on parle de 'padding' en général). J'imagine qu'on a la même garantie en C++ par souci de compatibilité ascendante avec le C.
Marc Boyer -- Si tu peux supporter d'entendre tes paroles Travesties par des gueux pour exciter des sots IF -- Rudyard Kipling (Trad. Paul Éluard)
Le 13-07-2006, ALB <lebatteux@crans.org> a écrit :
dans l'exemple suivant,
class point2d {
int x;
int y;
// des methodes
};
point2d A;
peut-on être sûr que les entiers x et y se suivent en
mémoire,quelque soit le compileur ? ( a-t-on *(&(A.x)+1) = A.y ?)
Surement pas, vu que c'était déjà faux en C avec les structs.
En C, on était sur d'avoir x avant y mais il peux y avoir
un 'trou' entre (on parle de 'padding' en général).
J'imagine qu'on a la même garantie en C++ par souci
de compatibilité ascendante avec le C.
Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)
peut-on être sûr que les entiers x et y se suivent en mémoire,quelque soit le compileur ? ( a-t-on *(&(A.x)+1) = A.y ?)
Surement pas, vu que c'était déjà faux en C avec les structs. En C, on était sur d'avoir x avant y mais il peux y avoir un 'trou' entre (on parle de 'padding' en général). J'imagine qu'on a la même garantie en C++ par souci de compatibilité ascendante avec le C.
Marc Boyer -- Si tu peux supporter d'entendre tes paroles Travesties par des gueux pour exciter des sots IF -- Rudyard Kipling (Trad. Paul Éluard)
Fabien LE LEZ
On 13 Jul 2006 06:09:02 -0700, "ALB" :
class point2d { int x; int y; // des methodes };
peut-on être sûr
Non. Je crois qu'on a quelques assurances de ce style (pas forcément celle-là) quand la classe en question est un POD (i.e. grosso modo une struct acceptable par un compilateur C). À partir du moment où il y a des fonctions membres, on n'est sûr de rien.
On 13 Jul 2006 06:09:02 -0700, "ALB" <lebatteux@crans.org>:
class point2d {
int x;
int y;
// des methodes
};
peut-on être sûr
Non.
Je crois qu'on a quelques assurances de ce style (pas forcément
celle-là) quand la classe en question est un POD (i.e. grosso modo une
struct acceptable par un compilateur C).
À partir du moment où il y a des fonctions membres, on n'est sûr de
rien.
Non. Je crois qu'on a quelques assurances de ce style (pas forcément celle-là) quand la classe en question est un POD (i.e. grosso modo une struct acceptable par un compilateur C). À partir du moment où il y a des fonctions membres, on n'est sûr de rien.
adebaene
ALB wrote:
dans l'exemple suivant,
class point2d { int x; int y; // des methodes };
point2d A;
peut-on être sûr que les entiers x et y se suivent en mémoire,quelque soit le compileur ? ( a-t-on *(&(A.x)+1) = A.y ?)
si, oui : class point3d : foo { int z; // des methodes };
point3d B;
peut-on être sûr que les entiers x, y et z se suivent en mémoire,quelque soit le compileur ? ( a-t-on *(&(B.x)+2) = B.z ?)
Non, on n'a pas ces garnaties. Il est généralement possible de les obtenir avec des extensions spécifiques au compilateur ("#pragma pack" ou quelque chose de ressemblant), mais c'esr rarement une bonne idée parce que : - c'est non portable. - sur certains processeurs (à peu près tous sauf les x86), il est impossible de faire des accès mémoire non alignés, donc le compilaateur est *forcé* d'aligner les variables comme le souhaite le processeur. - Sur les processeurs qui acceptent les accès mémoire non alignés, cela à un impact significatif sur les performances (typiquement, ca double le temps d'accès à une variable). - Généralement, quand on veut faire çà, c'est signe d'une mauvaise conception : on veut mapper une structure sur le contenu binaire d'un fichier ou d'un flux réseau, ou bien, sur des données déjà existantes en mémoire. Dans ces cas, la bonne solution consiste à laisser le compilateur aligner la structure comme il le souhaite et ajouter des fonctions pour sérialiser/désérialiser la structure vers/depuis l'autre représentation
Arnaud
ALB wrote:
dans l'exemple suivant,
class point2d {
int x;
int y;
// des methodes
};
point2d A;
peut-on être sûr que les entiers x et y se suivent en
mémoire,quelque soit le compileur ? ( a-t-on *(&(A.x)+1) = A.y ?)
si, oui :
class point3d : foo {
int z;
// des methodes
};
point3d B;
peut-on être sûr que les entiers x, y et z se suivent en
mémoire,quelque soit le compileur ? ( a-t-on *(&(B.x)+2) = B.z ?)
Non, on n'a pas ces garnaties. Il est généralement possible de les
obtenir avec des extensions spécifiques au compilateur ("#pragma pack"
ou quelque chose de ressemblant), mais c'esr rarement une bonne idée
parce que :
- c'est non portable.
- sur certains processeurs (à peu près tous sauf les x86), il est
impossible de faire des accès mémoire non alignés, donc le
compilaateur est *forcé* d'aligner les variables comme le souhaite le
processeur.
- Sur les processeurs qui acceptent les accès mémoire non alignés,
cela à un impact significatif sur les performances (typiquement, ca
double le temps d'accès à une variable).
- Généralement, quand on veut faire çà, c'est signe d'une mauvaise
conception : on veut mapper une structure sur le contenu binaire d'un
fichier ou d'un flux réseau, ou bien, sur des données déjà
existantes en mémoire. Dans ces cas, la bonne solution consiste à
laisser le compilateur aligner la structure comme il le souhaite et
ajouter des fonctions pour sérialiser/désérialiser la structure
vers/depuis l'autre représentation
peut-on être sûr que les entiers x et y se suivent en mémoire,quelque soit le compileur ? ( a-t-on *(&(A.x)+1) = A.y ?)
si, oui : class point3d : foo { int z; // des methodes };
point3d B;
peut-on être sûr que les entiers x, y et z se suivent en mémoire,quelque soit le compileur ? ( a-t-on *(&(B.x)+2) = B.z ?)
Non, on n'a pas ces garnaties. Il est généralement possible de les obtenir avec des extensions spécifiques au compilateur ("#pragma pack" ou quelque chose de ressemblant), mais c'esr rarement une bonne idée parce que : - c'est non portable. - sur certains processeurs (à peu près tous sauf les x86), il est impossible de faire des accès mémoire non alignés, donc le compilaateur est *forcé* d'aligner les variables comme le souhaite le processeur. - Sur les processeurs qui acceptent les accès mémoire non alignés, cela à un impact significatif sur les performances (typiquement, ca double le temps d'accès à une variable). - Généralement, quand on veut faire çà, c'est signe d'une mauvaise conception : on veut mapper une structure sur le contenu binaire d'un fichier ou d'un flux réseau, ou bien, sur des données déjà existantes en mémoire. Dans ces cas, la bonne solution consiste à laisser le compilateur aligner la structure comme il le souhaite et ajouter des fonctions pour sérialiser/désérialiser la structure vers/depuis l'autre représentation
Arnaud
kanze
Fabien LE LEZ wrote:
On 13 Jul 2006 06:09:02 -0700, "ALB" :
class point2d { int x; int y; // des methodes };
peut-on être sûr
Non.
Je crois qu'on a quelques assurances de ce style (pas forcément celle-là) quand la classe en question est un POD (i.e. grosso modo une struct acceptable par un compilateur C).
Même pas. Comme l'a déjà indiqué Marc, on ne les a même pas en C.
À partir du moment où il y a des fonctions membres, on n'est sûr de rien.
L'ajonction des fonctions membres n'empêche pas à une classe d'être un POD. La présence des membres privés, en revanche, si.
-- James Kanze GABI Software 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
Fabien LE LEZ wrote:
On 13 Jul 2006 06:09:02 -0700, "ALB" <lebatteux@crans.org>:
class point2d {
int x;
int y;
// des methodes
};
peut-on être sûr
Non.
Je crois qu'on a quelques assurances de ce style (pas
forcément celle-là) quand la classe en question est un POD
(i.e. grosso modo une struct acceptable par un compilateur C).
Même pas. Comme l'a déjà indiqué Marc, on ne les a même pas en
C.
À partir du moment où il y a des fonctions membres, on n'est
sûr de rien.
L'ajonction des fonctions membres n'empêche pas à une classe
d'être un POD. La présence des membres privés, en revanche, si.
--
James Kanze GABI Software
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
Je crois qu'on a quelques assurances de ce style (pas forcément celle-là) quand la classe en question est un POD (i.e. grosso modo une struct acceptable par un compilateur C).
Même pas. Comme l'a déjà indiqué Marc, on ne les a même pas en C.
À partir du moment où il y a des fonctions membres, on n'est sûr de rien.
L'ajonction des fonctions membres n'empêche pas à une classe d'être un POD. La présence des membres privés, en revanche, si.
-- James Kanze GABI Software 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
ALB
merci. Au moins, c'est clair et sans appel.
C'est dommage... En fait, pour mes besoins (gestion de propriétés géométriques), j'utilise des class à peu près comme je l'ai décris (la 3D herite de la 2D).
A un moment, je passe à une représentation graphique via OpenGL et je trouvais dommage de faire des glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir directement accès à un tableau de 3 éléments successifs (histoire d'economiser des indirections inutiles dans des cas un peu plus emboités et utiliser glVertex3iv).
ALB
merci. Au moins, c'est clair et sans appel.
C'est dommage...
En fait, pour mes besoins (gestion de propriétés géométriques),
j'utilise des class à peu près comme je l'ai décris (la 3D herite de
la 2D).
A un moment, je passe à une représentation graphique via OpenGL et je
trouvais dommage de faire des
glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir
directement accès à un tableau de 3 éléments successifs (histoire
d'economiser des indirections inutiles dans des cas un peu plus
emboités et utiliser glVertex3iv).
C'est dommage... En fait, pour mes besoins (gestion de propriétés géométriques), j'utilise des class à peu près comme je l'ai décris (la 3D herite de la 2D).
A un moment, je passe à une représentation graphique via OpenGL et je trouvais dommage de faire des glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir directement accès à un tableau de 3 éléments successifs (histoire d'economiser des indirections inutiles dans des cas un peu plus emboités et utiliser glVertex3iv).
ALB
Marc Boyer
Le 13-07-2006, ALB a écrit :
A un moment, je passe à une représentation graphique via OpenGL et je trouvais dommage de faire des glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir directement accès à un tableau de 3 éléments successifs (histoire d'economiser des indirections inutiles dans des cas un peu plus emboités et utiliser glVertex3iv).
Il y a bien des moyens de le faire en C++, ie maintenir les deux chose (x,y,z) + un tableau (ou un vecteur) ou de ne garder que le tableau/vecteur et de faire des accesseurs x,y,z, de manière à ce que le tout soit cohérent, mais au prix d'une surconsommation mémoire et/ou de CPU.
Je ne pense pas que le jeux en vaille la chandelle.
Marc Boyer -- Si tu peux supporter d'entendre tes paroles Travesties par des gueux pour exciter des sots IF -- Rudyard Kipling (Trad. Paul Éluard)
Le 13-07-2006, ALB <lebatteux@crans.org> a écrit :
A un moment, je passe à une représentation graphique via OpenGL et je
trouvais dommage de faire des
glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir
directement accès à un tableau de 3 éléments successifs (histoire
d'economiser des indirections inutiles dans des cas un peu plus
emboités et utiliser glVertex3iv).
Il y a bien des moyens de le faire en C++, ie maintenir
les deux chose (x,y,z) + un tableau (ou un vecteur)
ou de ne garder que le tableau/vecteur et de faire
des accesseurs x,y,z, de manière à ce que le tout
soit cohérent, mais au prix d'une surconsommation
mémoire et/ou de CPU.
Je ne pense pas que le jeux en vaille la chandelle.
Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)
A un moment, je passe à une représentation graphique via OpenGL et je trouvais dommage de faire des glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir directement accès à un tableau de 3 éléments successifs (histoire d'economiser des indirections inutiles dans des cas un peu plus emboités et utiliser glVertex3iv).
Il y a bien des moyens de le faire en C++, ie maintenir les deux chose (x,y,z) + un tableau (ou un vecteur) ou de ne garder que le tableau/vecteur et de faire des accesseurs x,y,z, de manière à ce que le tout soit cohérent, mais au prix d'une surconsommation mémoire et/ou de CPU.
Je ne pense pas que le jeux en vaille la chandelle.
Marc Boyer -- Si tu peux supporter d'entendre tes paroles Travesties par des gueux pour exciter des sots IF -- Rudyard Kipling (Trad. Paul Éluard)
Arnaud Meurgues
ALB wrote:
A un moment, je passe à une représentation graphique via OpenGL et je trouvais dommage de faire des glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir directement accès à un tableau de 3 éléments successifs (histoire d'economiser des indirections inutiles dans des cas un peu plus emboités et utiliser glVertex3iv).
Pourquoi ne pas utiliser dans la classe un int[3] ou, mieux, un vector<int> ?
-- Arnaud
ALB wrote:
A un moment, je passe à une représentation graphique via OpenGL et je
trouvais dommage de faire des
glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir
directement accès à un tableau de 3 éléments successifs (histoire
d'economiser des indirections inutiles dans des cas un peu plus
emboités et utiliser glVertex3iv).
Pourquoi ne pas utiliser dans la classe un int[3] ou, mieux, un
vector<int> ?
A un moment, je passe à une représentation graphique via OpenGL et je trouvais dommage de faire des glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir directement accès à un tableau de 3 éléments successifs (histoire d'economiser des indirections inutiles dans des cas un peu plus emboités et utiliser glVertex3iv).
Pourquoi ne pas utiliser dans la classe un int[3] ou, mieux, un vector<int> ?
-- Arnaud
ALB
Pourquoi ne pas utiliser dans la classe un int[3] ou, mieux, un vector<int> ?
je perds alors l'heritage. A moins qu'il y ait une astuce de vieux sioux ?
Pourquoi ne pas utiliser dans la classe un int[3] ou, mieux, un
vector<int> ?
je perds alors l'heritage.
A moins qu'il y ait une astuce de vieux sioux ?
Mais on perd un peu la sémantique de l'héritage dans le sens où si on affecte un Point3D à un Point2D, la composante z reste en mémoire, mais innacessible...
Donc, est-ce que tout cela a un intérêt ? Pas sur...
Marc Boyer -- Si tu peux supporter d'entendre tes paroles Travesties par des gueux pour exciter des sots IF -- Rudyard Kipling (Trad. Paul Éluard)
Le 13-07-2006, ALB <lebatteux@crans.org> a écrit :
Pourquoi ne pas utiliser dans la classe un int[3] ou, mieux, un
vector<int> ?
je perds alors l'heritage.
A moins qu'il y ait une astuce de vieux sioux ?
Ce ne serait pas beau, mais on pourrait imaginer (non compilé)
Mais on perd un peu la sémantique de l'héritage dans le
sens où si on affecte un Point3D à un Point2D, la composante
z reste en mémoire, mais innacessible...
Donc, est-ce que tout cela a un intérêt ? Pas sur...
Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)
Mais on perd un peu la sémantique de l'héritage dans le sens où si on affecte un Point3D à un Point2D, la composante z reste en mémoire, mais innacessible...
Donc, est-ce que tout cela a un intérêt ? Pas sur...
Marc Boyer -- Si tu peux supporter d'entendre tes paroles Travesties par des gueux pour exciter des sots IF -- Rudyard Kipling (Trad. Paul Éluard)
Sylvain Togni
A un moment, je passe à une représentation graphique via OpenGL et je trouvais dommage de faire des glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir directement accès à un tableau de 3 éléments successifs (histoire d'economiser des indirections inutiles dans des cas un peu plus emboités et utiliser glVertex3iv).
Reste la solution suivante:
class Point3D { public: Point(int x, int y, int z) {x() = x; y() = y; z() = z}
int const& x() const {return v[0];} int const& y() const {return v[1];} int const& z() const {return v[2];} int& x() {return v[0];} int& y() {return v[1];} int& z() {return v[2];}
int const* data() const {return v;} int* data() {return v;}
private: int v[3]; };
Au niveau performances, il ne devrait y avoir aucune pénalité car les functions sont inline. Par contre le prix à payer est de devoir écrire "p.x()" au lieu de simplement "p.x".
-- Sylvain Togni
A un moment, je passe à une représentation graphique via OpenGL et je
trouvais dommage de faire des
glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir
directement accès à un tableau de 3 éléments successifs (histoire
d'economiser des indirections inutiles dans des cas un peu plus
emboités et utiliser glVertex3iv).
Reste la solution suivante:
class Point3D
{
public:
Point(int x, int y, int z) {x() = x; y() = y; z() = z}
int const& x() const {return v[0];}
int const& y() const {return v[1];}
int const& z() const {return v[2];}
int& x() {return v[0];}
int& y() {return v[1];}
int& z() {return v[2];}
int const* data() const {return v;}
int* data() {return v;}
private:
int v[3];
};
Au niveau performances, il ne devrait y avoir aucune pénalité
car les functions sont inline. Par contre le prix à payer est
de devoir écrire "p.x()" au lieu de simplement "p.x".
A un moment, je passe à une représentation graphique via OpenGL et je trouvais dommage de faire des glVertex3i(pPoint->x,pPoint->y,pPoint->z); si je pouvais avoir directement accès à un tableau de 3 éléments successifs (histoire d'economiser des indirections inutiles dans des cas un peu plus emboités et utiliser glVertex3iv).
Reste la solution suivante:
class Point3D { public: Point(int x, int y, int z) {x() = x; y() = y; z() = z}
int const& x() const {return v[0];} int const& y() const {return v[1];} int const& z() const {return v[2];} int& x() {return v[0];} int& y() {return v[1];} int& z() {return v[2];}
int const* data() const {return v;} int* data() {return v;}
private: int v[3]; };
Au niveau performances, il ne devrait y avoir aucune pénalité car les functions sont inline. Par contre le prix à payer est de devoir écrire "p.x()" au lieu de simplement "p.x".