51 votes

Pourquoi S :: x n'est-il pas utilisé?

Prenons cet exemple de cppreference:

struct S { static const int x = 1; };
void f() { &S::x; } // discarded-value expression does not odr-use S::x

Je suis d'accord qu' &S::x est un rebut de la valeur de l'expression, étant donné que la norme dit (9.2, paragraphe 1 [stmt.expr] de n4700)

L'Expression des énoncés de la forme

expression-statement:
    expression_opt ;

L'expression est un jeté de la valeur de l'expression (article 8)...

Cependant, est-ce suffisant pour l' S::x à ne pas être odr-utilisé? 6.2, paragraphe 3 [de base.def.odr] les états

Une variable x dont le nom apparaît comme potentiellement-de l'expression évaluée ex est odr-utilisée par ex , à moins que

  • ...
  • si x est un objet, ex est un élément de l'ensemble des résultats possibles d'une expression e, où
    • la lvalue-à-rvalue de conversion (7.1) est appliquée à l' e, ou
    • e est un jeté de la valeur de l'expression (article 8).

Le problème est que le rebut de la valeur de l'expression &S::x n'a pas de potentiel de résultats (ce qui signifie qu' S::x n'est pas un résultat possible de l' &S::x), comme vous pouvez le voir à partir de 6.2, paragraphe 2 [de base.def.odr]:

... L'ensemble des résultats possibles d'une expression e est définie comme suit:

  • Si e est un id-expression (8.1.4), l'ensemble ne contient qu' e.
  • Si e est un subscripting opération (8.2.1) avec un tableau opérande, l'ensemble contient les résultats potentiels de l'opérande.
  • ...
  • Sinon, l'ensemble est vide.

Alors, comment pouvez-vous expliquer qu' S::x n'est pas odr-utilisé?

5voto

T.C. Points 22510

C'est en effet odr-utilisé. Votre analyse est correcte (et j'ai corrigé cet exemple il y a quelque temps ).

0voto

YSC Points 3386

Oui, dans l'exemple, &S::x odr-utilise S::x.

[basic.def.odr]/4

Une variable x dont le nom apparaît comme potentiellement-de l'expression évaluée ex est odr-utilisée par ex , à moins que l'application de la lvalue-à-rvalue conversion en x rendements d'une expression constante qui n'a pas invoquer la non-trivial fonctions et, si x est un objet, ex est un élément de l'ensemble des résultats possibles d'une expression e, où la lvalue-à-rvalue de conversion est appliqué à e, ou e est un jeté de la valeur de l'expression.

L'adresse d'un objet n'est jamais une expression constante. C'est pourquoi, S::x est odr-utilisés en &S::x.

Afin de justifier cette dernière affirmation:

[expr.const]/6

Une expression constante est un glvalue base constante de l'expression qui fait référence à une entité qui est autorisée résultat d'une expression constante (comme défini ci-dessous), ou un prvalue core expression constante dont la valeur satisfait les contraintes suivantes [...]

et

[expr.const]/2.7

2) Une expression e est une base constante de l'expression , à moins que l'évaluation de l' e, suivant les règles de la machine abstraite, permettrait d'évaluer l'une des expressions suivantes:
[...]
2.7) une lvalue-à-rvalue conversion sauf si elle est appliquée à

(aucun des points suivants s'applique:)

2.7.1) non volatile glvalue de l'intégrale ou type d'énumération qui se réfère à un complet non-volatile const objet avec un précédent initialisation, initialisé avec une expression constante, ou
2.7.2) un non-volatile glvalue qui fait référence à un sous-objet d'un littéral de chaîne, ou
2.7.3) un non-volatile glvalue qui fait référence à un non-volatile de l'objet défini avec constexpr, ou qui renvoie à un non-mutable sous-objet d'un tel objet, ou
2.7.4) un non-volatile glvalue littérale type qui fait référence à un non-volatile de l'objet dont la durée de vie a commencé dans l'évaluation de l' e;

-3voto

SHR Points 5607

Lors de la déclaration d' const int, il peut être entièrement écartée par le compilateur, à moins que vous à l'aide de son adresse. en prenant l'adresse n'est pas assez.

Jetés n'est pas la valeur n'est pas évalué, il est, mais il n'y a pas d'adresse mémoire contenant la const valeur, le compilateur il suffit de remplacer la variable const par sa valeur, que c'était juste une macro.

En outre, lors de la prise d'un pointeur vers elle, et la valeur du pointeur, n'impressionne pas le compilateur beaucoup, il l'ignore et l'utilisation de la valeur.

Le code suivant montre, ce code peut être compilé et exécuté (je l'ai tester par plusieurs compilateurs, je ne suis toujours pas sûr si c'compilé avec succès par tous...) malgré le fait qu' S::x n'a pas été déclarée:

#include <iostream>
using namespace std;
struct S
{
    static const int x=0; 
};
//const int S::x; //discarded
int main()
{
    const int *px = &S::x;  //taking the address
    cout<< *px <<endl; //print the value - OK
    return 0;
}

Mais si je vais essayer d'utiliser l'adresse elle-même(pas la valeur) comme:

cout<< px <<endl; //print the address - Will be failed

le lien a échoué dou pour: "undefined reference to S::x".

Donc, ma conclusion est la suivante: en prenant une adresse sans l'utiliser, ne compte pas du tout.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X