[Edit: OK, donc cette question est plus subtile que ce que je pensais au premier abord.]
Déclaration d'un pointeur vers const ou de référence-de-const n'aide jamais un compilateur d'optimiser quoi que ce soit. (Bien que de voir la mise à Jour au bas de cette réponse.)
L' const
déclaration indique seulement comment un identifiant sera utilisé à l'intérieur de la portée de sa déclaration; il ne dit pas que l'objet sous-jacent ne peut pas le changer.
Exemple:
int foo(const int *p) {
int x = *p;
bar(x);
x = *p;
return x;
}
Le compilateur ne peut pas supposer qu' *p
n'est pas modifié par l'appel à l' bar()
car p
pourrait être (par exemple) un pointeur vers un mondial int et bar()
pourra la modifier.
Si le compilateur sait assez sur l'appelant de foo()
et le contenu de bar()
qu'il peut prouver bar()
ne modifie pas *p
, alors il peut aussi réaliser que la preuve sans le const déclaration.
Mais c'est vrai en général. Parce qu' const
seulement a un effet dans le champ d'application de la déclaration, le compilateur peut déjà voir comment vous traitez le pointeur ou une référence dans cette étendue; il sait déjà que vous n'êtes pas la modification de l'objet sous-jacent.
Donc, en bref, tous const
t dans ce contexte est de vous empêcher de faire des erreurs. Il n'a pas d'indiquer au compilateur tout ce qu'il ne connaissent pas déjà, et par conséquent, il n'est pas pertinent pour l'optimisation.
Quid des fonctions qui appellent foo()
? Comme:
int x = 37;
foo(&x);
printf("%d\n", x);
Le compilateur prouver que cela s'imprime 37, depuis foo()
prend un const int *
?
Pas de. Même si foo()
prend un pointeur-à-const, cela pourrait jeter la const-ness loin et modifier le type int. (C'est pas un comportement non défini.) Ici encore, le compilateur ne peut pas faire d'hypothèses en général; et si elle en sait assez sur foo()
de faire une telle optimisation, il va savoir que, même sans le const
.
La seule fois const
pourrait permettre des optimisations est des cas comme ceci:
const int x = 37;
foo(&x);
printf("%d\n", x);
Ici, à modifier x
par quelque mécanisme que ce soit (par exemple, en prenant un pointeur et jetant l' const
) est d'invoquer un Comportement Indéfini. Ainsi, le compilateur est libre de penser que vous ne le faites pas, et il peut se propager à la constante de 37 dans le printf(). Ce type d'optimisation est légal pour n'importe quel objet vous déclarez const
. (Dans la pratique, une variable locale à laquelle vous ne prenez jamais de référence ne sera pas en bénéficier, car le compilateur ne peut déjà voir si vous les modifiez dans son champ d'application.)
Pour répondre à votre "note de côté" de la question, (un) const pointeur est un pointeur; et (b) un pointeur const peut être égal à NULL. Il est exact que la représentation interne (c'est à dire une adresse) est probablement la même.
[mise à jour]
Comme Christoph points dans les commentaires, ma réponse est incomplète car elle ne fait pas mention d' restrict
.
Section 6.7.3.1 (4) de la standard C99 dit:
Lors de chaque exécution de B, soit L tout lvalue qui a &L selon P. Si L est utilisé pour
accéder à la valeur de l'objet X qu'il désigne, et X est également modifiée (par tous moyens),
les exigences suivantes s'appliquent: T ne sera pas const-qualifiés. ...
(Ici B est un bloc de base sur laquelle P, restreindre l'-pointeur-de-T, est dans le domaine.)
Donc, si une fonction C foo()
est déclaré comme ceci:
foo(const int * restrict p)
...puis le compilateur peut supposer que l'absence de modification de *p
se produisent au cours de la durée de vie d' p
-- c'est à dire, lors de l'exécution de l' foo()
-- parce que sinon, le Comportement est Indéfini.
Donc, en principe, combinant restrict
avec un pointeur-à-const pourrait permettre à la fois de les optimisations qui sont licenciés ci-dessus. Ne les compilateurs de mettre en œuvre une telle optimisation, je me demande? (GCC 4.5.2, au moins, ne l'est pas.)
Notez que restrict
n'existe que dans C, pas du C++ (même pas de C++0x), sauf un compilateur spécifique de l'extension.