Est-ce possible de déclarer une propriété de même classe que celle qui la possède ?
class A { A a; };
Je suis vraiment trop con. C'est conceptuellement idiot ;)
non, ni idiot, ni inutile;
Si si, je voulais *vraiment* que A contient une instance de lui-même en propriété et pas une référence ;). Quel idiot...
cela peut même être une façon de coder un noeud dans un arbre ou une liste chainée (ok, depuis std::/set/ qui ferait ça?).
l'auto-référencement impose simplement que la donnée membre soit une référence ou un pointeur (les 2 valant pour un pointeur de taille connu alors que la classe est de taille inconnue lorsque la donnée 'a' est parsée - ce qui provoque l'impossibilité de compiler).
donc:
class A { A& a; A(A another) : a(another) { ... } };
Pour le cas du pointeur, c'est trivial, par contre pour les références, j'aimerais un exemple qui compile dans ce cas et utilisable car je n'y arrive pas.
class A { public: A() : a( *this ) {}
private: A& a ; } ;
Quant à l'utilité, c'est autre chose:-). Dans la pratique, quand on veut une référence au même type dans un objet, c'est pour la navigation, et il faut pouvoir changer le référé dynamiquement. Ce qui veut dire pointeur, et non référence.
Puisqu'il faut forcément fournir un nouveau A au constructeur de A, comment créer un A "originel" sans rien lui fournir ?
Il y a toujours *this.
-- 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
Azuriel wrote:
Azuriel wrote on 28/09/2006 19:34:
Est-ce possible de déclarer une propriété de même classe que celle
qui la possède ?
class A
{
A a;
};
Je suis vraiment trop con. C'est conceptuellement idiot ;)
non, ni idiot, ni inutile;
Si si, je voulais *vraiment* que A contient une instance de
lui-même en propriété et pas une référence ;). Quel idiot...
cela peut même être une façon de coder un noeud dans un
arbre ou une liste chainée (ok, depuis std::/set/ qui ferait
ça?).
l'auto-référencement impose simplement que la donnée membre
soit une référence ou un pointeur (les 2 valant pour un
pointeur de taille connu alors que la classe est de taille
inconnue lorsque la donnée 'a' est parsée - ce qui provoque
l'impossibilité de compiler).
donc:
class A {
A& a;
A(A another) : a(another) { ... }
};
Pour le cas du pointeur, c'est trivial, par contre pour les
références, j'aimerais un exemple qui compile dans ce cas et
utilisable car je n'y arrive pas.
class A
{
public:
A() : a( *this ) {}
private:
A& a ;
} ;
Quant à l'utilité, c'est autre chose:-). Dans la pratique, quand
on veut une référence au même type dans un objet, c'est pour la
navigation, et il faut pouvoir changer le référé dynamiquement.
Ce qui veut dire pointeur, et non référence.
Puisqu'il faut forcément fournir un nouveau A au constructeur
de A, comment créer un A "originel" sans rien lui fournir ?
Il y a toujours *this.
--
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
Est-ce possible de déclarer une propriété de même classe que celle qui la possède ?
class A { A a; };
Je suis vraiment trop con. C'est conceptuellement idiot ;)
non, ni idiot, ni inutile;
Si si, je voulais *vraiment* que A contient une instance de lui-même en propriété et pas une référence ;). Quel idiot...
cela peut même être une façon de coder un noeud dans un arbre ou une liste chainée (ok, depuis std::/set/ qui ferait ça?).
l'auto-référencement impose simplement que la donnée membre soit une référence ou un pointeur (les 2 valant pour un pointeur de taille connu alors que la classe est de taille inconnue lorsque la donnée 'a' est parsée - ce qui provoque l'impossibilité de compiler).
donc:
class A { A& a; A(A another) : a(another) { ... } };
Pour le cas du pointeur, c'est trivial, par contre pour les références, j'aimerais un exemple qui compile dans ce cas et utilisable car je n'y arrive pas.
class A { public: A() : a( *this ) {}
private: A& a ; } ;
Quant à l'utilité, c'est autre chose:-). Dans la pratique, quand on veut une référence au même type dans un objet, c'est pour la navigation, et il faut pouvoir changer le référé dynamiquement. Ce qui veut dire pointeur, et non référence.
Puisqu'il faut forcément fournir un nouveau A au constructeur de A, comment créer un A "originel" sans rien lui fournir ?
Il y a toujours *this.
-- 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
kanze
Sylvain wrote:
Azuriel wrote on 28/09/2006 20:17:
class A { A& a; A(A another) : a(another) { ... } };
Pour le cas du pointeur, c'est trivial, par contre pour les référen ces, j'aimerais un exemple qui compile dans ce cas et utilisable car je n'y arrive pas. Puisqu'il faut forcément fournir un nouveau A au constructeur de A, comment créer un A "originel" sans rien lui fournir ?
;-) !
faute de pouvoir ne rien lui fournir, on peut lui fournir rien en le faisant passer pour qlq chose ...
A* first = null; A a(*first);
une référence (hormis la simplification syntaxique) est l'équivalent d'un pointeur, donc on peut lui affecter une valeur nulle (tester cette valeur ne conduira pas à un code très clean mais bon ...).
D'où tu as ça ? Ce n'est pas du tout le cas en C++. Où ton *first as déjà un comportement indéfini, et provoquait un core dump avec au moins un compilateur dont je me suis servi.
-- 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
Sylvain wrote:
Azuriel wrote on 28/09/2006 20:17:
class A {
A& a;
A(A another) : a(another) { ... }
};
Pour le cas du pointeur, c'est trivial, par contre pour les référen ces,
j'aimerais un exemple qui compile dans ce cas et utilisable car je n'y
arrive pas.
Puisqu'il faut forcément fournir un nouveau A au constructeur de A,
comment créer un A "originel" sans rien lui fournir ?
;-) !
faute de pouvoir ne rien lui fournir, on peut lui fournir rien
en le faisant passer pour qlq chose ...
A* first = null;
A a(*first);
une référence (hormis la simplification syntaxique) est
l'équivalent d'un pointeur, donc on peut lui affecter une
valeur nulle (tester cette valeur ne conduira pas à un code
très clean mais bon ...).
D'où tu as ça ? Ce n'est pas du tout le cas en C++. Où ton
*first as déjà un comportement indéfini, et provoquait un core
dump avec au moins un compilateur dont je me suis servi.
--
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
class A { A& a; A(A another) : a(another) { ... } };
Pour le cas du pointeur, c'est trivial, par contre pour les référen ces, j'aimerais un exemple qui compile dans ce cas et utilisable car je n'y arrive pas. Puisqu'il faut forcément fournir un nouveau A au constructeur de A, comment créer un A "originel" sans rien lui fournir ?
;-) !
faute de pouvoir ne rien lui fournir, on peut lui fournir rien en le faisant passer pour qlq chose ...
A* first = null; A a(*first);
une référence (hormis la simplification syntaxique) est l'équivalent d'un pointeur, donc on peut lui affecter une valeur nulle (tester cette valeur ne conduira pas à un code très clean mais bon ...).
D'où tu as ça ? Ce n'est pas du tout le cas en C++. Où ton *first as déjà un comportement indéfini, et provoquait un core dump avec au moins un compilateur dont je me suis servi.
-- 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
kanze
Sylvain wrote:
Michel Decima wrote on 28/09/2006 21:50:
Sylvain wrote:
faute de pouvoir ne rien lui fournir, on peut lui fournir rien en le faisant passer pour qlq chose ...
A* first = null; A a(*first);
Est ce que *first a un comportement defini si first vaut NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas la déférencement de first.
Le comité est en train de revoir la question, je crois (qui se présente dans des cas parfois inattendu), mais jusqu'à la nouvelle version de la norme, au moin, c'est bien un comportement indéfini. Et je me suis déjà servi d'au moins un compilateur qui le vérifier lors de l'exécution, et qui provoquait un core dump.
-- 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
Sylvain wrote:
Michel Decima wrote on 28/09/2006 21:50:
Sylvain wrote:
faute de pouvoir ne rien lui fournir, on peut lui fournir rien en le
faisant passer pour qlq chose ...
A* first = null;
A a(*first);
Est ce que *first a un comportement defini si first vaut NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas
la déférencement de first.
Le comité est en train de revoir la question, je crois (qui se
présente dans des cas parfois inattendu), mais jusqu'à la
nouvelle version de la norme, au moin, c'est bien un
comportement indéfini. Et je me suis déjà servi d'au moins un
compilateur qui le vérifier lors de l'exécution, et qui
provoquait un core dump.
--
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
faute de pouvoir ne rien lui fournir, on peut lui fournir rien en le faisant passer pour qlq chose ...
A* first = null; A a(*first);
Est ce que *first a un comportement defini si first vaut NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas la déférencement de first.
Le comité est en train de revoir la question, je crois (qui se présente dans des cas parfois inattendu), mais jusqu'à la nouvelle version de la norme, au moin, c'est bien un comportement indéfini. Et je me suis déjà servi d'au moins un compilateur qui le vérifier lors de l'exécution, et qui provoquait un core dump.
-- 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
Alexandre
class A { public: A() : a( *this ) {}
private: A& a ; } ;
Quant à l'utilité, c'est autre chose:-). Dans la pratique, quand on veut une référence au même type dans un objet, c'est pour la navigation, et il faut pouvoir changer le référé dynamiquement. Ce qui veut dire pointeur, et non référence.
je m'en suis servi une fois (pour un cas d'école il est vrai). Une classe modélisant une personne, avec des références sur les parents (qui sont des personnes). On peut bien sur prendre des pointeurs, mais ça me semblait plus logique, la référence (les parents on les a depuis la naissance et ils ne changent pas). Mais se posait alors le problème de la première personne... et donc qui *doit* être son propre père et sa propre mère...
class A
{
public:
A() : a( *this ) {}
private:
A& a ;
} ;
Quant à l'utilité, c'est autre chose:-). Dans la pratique, quand
on veut une référence au même type dans un objet, c'est pour la
navigation, et il faut pouvoir changer le référé dynamiquement.
Ce qui veut dire pointeur, et non référence.
je m'en suis servi une fois (pour un cas d'école il est vrai). Une classe
modélisant une personne, avec des références sur les parents (qui sont des
personnes). On peut bien sur prendre des pointeurs, mais ça me semblait plus
logique, la référence (les parents on les a depuis la naissance et ils ne
changent pas). Mais se posait alors le problème de la première personne...
et donc qui *doit* être son propre père et sa propre mère...
Quant à l'utilité, c'est autre chose:-). Dans la pratique, quand on veut une référence au même type dans un objet, c'est pour la navigation, et il faut pouvoir changer le référé dynamiquement. Ce qui veut dire pointeur, et non référence.
je m'en suis servi une fois (pour un cas d'école il est vrai). Une classe modélisant une personne, avec des références sur les parents (qui sont des personnes). On peut bien sur prendre des pointeurs, mais ça me semblait plus logique, la référence (les parents on les a depuis la naissance et ils ne changent pas). Mais se posait alors le problème de la première personne... et donc qui *doit* être son propre père et sa propre mère...
dieu.tout.puissant
kanze wrote:
Sylvain wrote:
Michel Decima wrote on 28/09/2006 21:50:
Sylvain wrote:
faute de pouvoir ne rien lui fournir, on peut lui fournir rien en le faisant passer pour qlq chose ...
A* first = null; A a(*first);
Est ce que *first a un comportement defini si first vaut NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas la déférencement de first.
*first n'implique pas forcément un déréférencement 'mécanique' du pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est //utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au maximum). Si vous connaissez un compilateur pour lequel cette ligne ne passe pas, je serais intéressé d'en connaitre le nom.
kanze wrote:
Sylvain wrote:
Michel Decima wrote on 28/09/2006 21:50:
Sylvain wrote:
faute de pouvoir ne rien lui fournir, on peut lui fournir rien en le
faisant passer pour qlq chose ...
A* first = null;
A a(*first);
Est ce que *first a un comportement defini si first vaut NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas
la déférencement de first.
*first n'implique pas forcément un déréférencement 'mécanique' du
pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au
maximum). Si vous connaissez un compilateur pour lequel cette ligne ne
passe pas, je serais intéressé d'en connaitre le nom.
faute de pouvoir ne rien lui fournir, on peut lui fournir rien en le faisant passer pour qlq chose ...
A* first = null; A a(*first);
Est ce que *first a un comportement defini si first vaut NULL ?
quelle importance puisqu'il N'est PAS déréférencé ...
Et c'est quoi, exactement, l'expression *first, si ce n'est pas la déférencement de first.
*first n'implique pas forcément un déréférencement 'mécanique' du pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est //utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au maximum). Si vous connaissez un compilateur pour lequel cette ligne ne passe pas, je serais intéressé d'en connaitre le nom.
Michel Decima
*first n'implique pas forcément un déréférencement 'mécanique' du pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est //utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au maximum).
Qu'est ce qui JUSTIFIE cette affirmation dans la norme ?
*first n'implique pas forcément un déréférencement 'mécanique' du
pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au
maximum).
Qu'est ce qui JUSTIFIE cette affirmation dans la norme ?
*first n'implique pas forcément un déréférencement 'mécanique' du pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est //utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au maximum).
Qu'est ce qui JUSTIFIE cette affirmation dans la norme ?
dieu.tout.puissant
Michel Decima wrote:
*first n'implique pas forcément un déréférencement 'mécanique ' du pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est //utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au maximum).
Qu'est ce qui JUSTIFIE cette affirmation dans la norme ?
L'opération d'initialisation d'une référence. int &r = x;
2 cas : - "x" est une lvalue ("x" doit être du type de la référence) : l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas évalué. - "x" est une rvalue ("x" ne doit pas forcément être du type de la référence): Conversion implicite de type + création d'une variable temporaire. => "x" est évalué. A partir de là, l'initialisation possède un objet avec une adresse. Par conséquent, retour au premier cas.
De plus, un comportement non défini devrait (mais ce n'est pas toujours le cas...) générer de la part du compilateur uniquement un warning.
Michel Decima wrote:
*first n'implique pas forcément un déréférencement 'mécanique ' du
pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est
//utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au
maximum).
Qu'est ce qui JUSTIFIE cette affirmation dans la norme ?
L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une variable
temporaire. => "x" est évalué. A partir de là, l'initialisation
possède un objet avec une adresse. Par conséquent, retour au premier
cas.
De plus, un comportement non défini devrait (mais ce n'est pas
toujours le cas...) générer de la part du compilateur uniquement un
warning.
*first n'implique pas forcément un déréférencement 'mécanique ' du pointeur first.
int *p = 0;
int &r = *p; // pas de déréférencement, seule l'adresse est //utilisée => ok
int v = *p; // déréférencement => crash
La seconde ligne DOIT passer sur n'importe quel compilateur (warning au maximum).
Qu'est ce qui JUSTIFIE cette affirmation dans la norme ?
L'opération d'initialisation d'une référence. int &r = x;
2 cas : - "x" est une lvalue ("x" doit être du type de la référence) : l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas évalué. - "x" est une rvalue ("x" ne doit pas forcément être du type de la référence): Conversion implicite de type + création d'une variable temporaire. => "x" est évalué. A partir de là, l'initialisation possède un objet avec une adresse. Par conséquent, retour au premier cas.
De plus, un comportement non défini devrait (mais ce n'est pas toujours le cas...) générer de la part du compilateur uniquement un warning.
Michel Decima
L'opération d'initialisation d'une référence. int &r = x;
2 cas : - "x" est une lvalue ("x" doit être du type de la référence) : l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas évalué. - "x" est une rvalue ("x" ne doit pas forcément être du type de la référence): Conversion implicite de type + création d'une variable temporaire. => "x" est évalué. A partir de là, l'initialisation possède un objet avec une adresse. Par conséquent, retour au premier cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le resultat de la compilation ?
L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une variable
temporaire. => "x" est évalué. A partir de là, l'initialisation
possède un objet avec une adresse. Par conséquent, retour au premier
cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le resultat
de la compilation ?
L'opération d'initialisation d'une référence. int &r = x;
2 cas : - "x" est une lvalue ("x" doit être du type de la référence) : l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas évalué. - "x" est une rvalue ("x" ne doit pas forcément être du type de la référence): Conversion implicite de type + création d'une variable temporaire. => "x" est évalué. A partir de là, l'initialisation possède un objet avec une adresse. Par conséquent, retour au premier cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le resultat de la compilation ?
Falk Tannhäuser
schrieb:
L'opération d'initialisation d'une référence. int &r = x;
2 cas : - "x" est une lvalue ("x" doit être du type de la référence) : l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas évalué.
Aaah Bon Dieu qui es aux cieux ! Faut-il vraiment que moi, un misérable mortel, Vous cite l'Écriture Sainte - Psaume 8.3.2, Verset 4 :
[...] A reference shall be initialized to refer to a valid object or function. Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the object obtained by dereferencing a null pointer, which causes undefined behavior. [...]
- "x" est une rvalue ("x" ne doit pas forcément être du type de la référence): Conversion implicite de type + création d'une variable temporaire. => "x" est évalué. A partir de là, l'initialisation possède un objet avec une adresse. Par conséquent, retour au premier cas.
De plus, un comportement non défini devrait (mais ce n'est pas toujours le cas...) générer de la part du compilateur uniquement un warning.
Ou une erreur, ou un plantage, ou un reformattage du disque dur, ou rien du tout, ou une petite corruption de données de temps en temps...
Behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements. Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior. [Note: permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. ]
Amen, Falk
dieu.tout.puissant@gmail.com schrieb:
L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas
évalué.
Aaah Bon Dieu qui es aux cieux ! Faut-il vraiment que moi, un misérable
mortel, Vous cite l'Écriture Sainte - Psaume 8.3.2, Verset 4 :
[...] A reference shall be initialized to refer to a valid object or
function. Note: in particular, a null reference cannot exist in a
well-defined program, because the only way to create such a reference
would be to bind it to the object obtained by dereferencing a null
pointer, which causes undefined behavior. [...]
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une variable
temporaire. => "x" est évalué. A partir de là, l'initialisation
possède un objet avec une adresse. Par conséquent, retour au premier
cas.
De plus, un comportement non défini devrait (mais ce n'est pas
toujours le cas...) générer de la part du compilateur uniquement un
warning.
Ou une erreur, ou un plantage, ou un reformattage du disque dur, ou rien
du tout, ou une petite corruption de données de temps en temps...
Behavior, such as might arise upon use of an erroneous program construct
or erroneous data, for which this International Standard imposes no
requirements. Undefined behavior may also be expected when this
International Standard omits the description of any explicit definition
of behavior. [Note: permissible undefined behavior ranges from ignoring
the situation completely with unpredictable results, to behaving during
translation or program execution in a documented manner characteristic
of the environment (with or without the issuance of a diagnostic
message), to terminating a translation or execution (with the issuance
of a diagnostic message). Many erroneous program constructs do not
engender undefined behavior; they are required to be diagnosed. ]
L'opération d'initialisation d'une référence. int &r = x;
2 cas : - "x" est une lvalue ("x" doit être du type de la référence) : l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas évalué.
Aaah Bon Dieu qui es aux cieux ! Faut-il vraiment que moi, un misérable mortel, Vous cite l'Écriture Sainte - Psaume 8.3.2, Verset 4 :
[...] A reference shall be initialized to refer to a valid object or function. Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the object obtained by dereferencing a null pointer, which causes undefined behavior. [...]
- "x" est une rvalue ("x" ne doit pas forcément être du type de la référence): Conversion implicite de type + création d'une variable temporaire. => "x" est évalué. A partir de là, l'initialisation possède un objet avec une adresse. Par conséquent, retour au premier cas.
De plus, un comportement non défini devrait (mais ce n'est pas toujours le cas...) générer de la part du compilateur uniquement un warning.
Ou une erreur, ou un plantage, ou un reformattage du disque dur, ou rien du tout, ou une petite corruption de données de temps en temps...
Behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements. Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior. [Note: permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. ]
Amen, Falk
dieu.tout.puissant
Michel Decima wrote:
L'opération d'initialisation d'une référence. int &r = x;
2 cas : - "x" est une lvalue ("x" doit être du type de la référence) : l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas évalué. - "x" est une rvalue ("x" ne doit pas forcément être du type de la référence): Conversion implicite de type + création d'une variable temporaire. => "x" est évalué. A partir de là, l'initialisation possède un objet avec une adresse. Par conséquent, retour au premier cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le resultat de la compilation ?
*(int*) 0 Cette expression spécifie un objet de type int dont l'adresse est 0. (<=> définition d'une lvalue)
Définition d'une lvalue dans la norme c++ : lvalue : une expression qui réfère à un objet. A un autre endroit, la norme utilise également cette définition (équivalente dans la pratique): lvalue : un objet dont on peut prendre l'adresse.
[Précision à ce sujet : la norme c++ indique clairement qu'une lvalue n'est pas forcément un objet qui peut se placer à gauche de l'opérateur d'assignement, tel qu'on l'entend souvent.]
L'expression est donc une lvalue. Nous sommes dans le 1er cas. Le compilateur devrait laisser passer cette ligne (il ne devrait pas tenter un déréférencement).
Michel Decima wrote:
L'opération d'initialisation d'une référence.
int &r = x;
2 cas :
- "x" est une lvalue ("x" doit être du type de la référence) :
l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas
évalué.
- "x" est une rvalue ("x" ne doit pas forcément être du type de la
référence): Conversion implicite de type + création d'une variable
temporaire. => "x" est évalué. A partir de là, l'initialisation
possède un objet avec une adresse. Par conséquent, retour au premier
cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le resultat
de la compilation ?
*(int*) 0
Cette expression spécifie un objet de type int dont l'adresse est 0.
(<=> définition d'une lvalue)
Définition d'une lvalue dans la norme c++ :
lvalue : une expression qui réfère à un objet.
A un autre endroit, la norme utilise également cette définition
(équivalente dans la pratique):
lvalue : un objet dont on peut prendre l'adresse.
[Précision à ce sujet : la norme c++ indique clairement qu'une lvalue
n'est pas forcément un objet qui peut se placer à gauche de
l'opérateur d'assignement, tel qu'on l'entend souvent.]
L'expression est donc une lvalue.
Nous sommes dans le 1er cas.
Le compilateur devrait laisser passer cette ligne (il ne devrait pas
tenter un déréférencement).
L'opération d'initialisation d'une référence. int &r = x;
2 cas : - "x" est une lvalue ("x" doit être du type de la référence) : l'opération d'initialisation prend l'adresse de "x" => "x" n'est pas évalué. - "x" est une rvalue ("x" ne doit pas forcément être du type de la référence): Conversion implicite de type + création d'une variable temporaire. => "x" est évalué. A partir de là, l'initialisation possède un objet avec une adresse. Par conséquent, retour au premier cas.
Si je considere
int& r = *(int*)0;
dans lequel des 2 cas on se place ? Quel devrait etre le resultat de la compilation ?
*(int*) 0 Cette expression spécifie un objet de type int dont l'adresse est 0. (<=> définition d'une lvalue)
Définition d'une lvalue dans la norme c++ : lvalue : une expression qui réfère à un objet. A un autre endroit, la norme utilise également cette définition (équivalente dans la pratique): lvalue : un objet dont on peut prendre l'adresse.
[Précision à ce sujet : la norme c++ indique clairement qu'une lvalue n'est pas forcément un objet qui peut se placer à gauche de l'opérateur d'assignement, tel qu'on l'entend souvent.]
L'expression est donc une lvalue. Nous sommes dans le 1er cas. Le compilateur devrait laisser passer cette ligne (il ne devrait pas tenter un déréférencement).