Ignorons l'optimisation pour un moment, et pensons simplement à ce que la machine abstraite doit faire pour référencer une variable locale par rapport à une variable via un pointeur (local). Si nous avons des variables locales déclarées comme :
int i;
int *p;
lorsque nous référençons la valeur de i, le code non optimisé doit aller chercher la valeur qui se trouve (disons) à 12 au-delà du pointeur de pile actuel et la charger dans un registre pour que nous puissions travailler avec elle. Alors que lorsque nous faisons référence à *p, le même code non optimisé doit aller chercher la valeur de p à 16 après le pointeur de pile actuel, la charger dans un registre, puis aller chercher la valeur vers laquelle pointe le registre et la charger dans un autre registre afin de pouvoir travailler avec elle comme avant. La première partie du travail est la même, mais l'accès au pointeur implique conceptuellement une étape supplémentaire qui doit être effectuée avant que nous puissions travailler avec la valeur.
C'était, je pense, le but de la question de l'interview - voir si vous compreniez la différence fondamentale entre les deux types d'accès. Vous pensiez que l'accès à une variable locale impliquait une sorte de recherche, ce qui est le cas, mais l'accès à un pointeur implique ce même type de recherche pour obtenir la valeur du pointeur avant de pouvoir commencer à chercher l'objet pointé. En termes simples, non optimisés, l'accès au pointeur va être plus lent à cause de cette étape supplémentaire.
Maintenant, avec l'optimisation, il peut arriver que les deux temps soient très proches ou identiques. Il est vrai que si un autre code récent a déjà utilisé la valeur de p pour référencer une autre valeur, vous pouvez déjà trouver p dans un registre, de sorte que la recherche de *p via p prend le même temps que la recherche de i via le pointeur de pile. De la même manière, si vous avez récemment utilisé la valeur de i, vous pouvez déjà trouver il dans un registre. Et si la même chose peut être vraie pour la valeur de *p, l'optimiseur ne peut réutiliser sa valeur du registre que s'il est sûr que p n'a pas changé entre-temps. Il n'a aucun problème à réutiliser la valeur de i. En bref, si l'accès aux deux valeurs peut prendre le même temps avec l'optimisation, l'accès à la variable locale ne sera presque jamais plus lent (sauf dans des cas vraiment pathologiques), et peut très bien être plus rapide. C'est donc la réponse correcte à la question de l'enquêteur.
En présence de hiérarchies de mémoire, la différence de temps peut devenir encore plus prononcée. Les variables locales seront situées à proximité les unes des autres sur la pile, ce qui signifie que vous avez de grandes chances de trouver l'adresse dont vous avez besoin déjà dans la mémoire principale et dans le cache la première fois que vous y accédez (à moins qu'il ne s'agisse de la toute première variable locale à laquelle vous accédez dans cette routine). Il n'y a pas une telle garantie avec l'adresse vers laquelle pointe le pointeur. À moins qu'elle n'ait été accédée récemment, vous devrez peut-être attendre un manque de cache, ou même un défaut de page, pour accéder à l'adresse pointée, ce qui pourrait la rendre plus lente de plusieurs ordres de grandeur par rapport à la variable locale. Non, cela n'arrivera pas tout le temps - mais c'est un facteur potentiel qui pourrait faire une différence dans certains cas, et c'est aussi un point qui pourrait être soulevé par un candidat en réponse à une telle question.
Maintenant, qu'en est-il de la question soulevée par d'autres commentateurs : quelle importance cela a-t-il ? Il est vrai que, pour un accès unique, la différence sera minuscule en termes absolus, comme un grain de sable. Mais vous mettez suffisamment de grains de sable ensemble et vous obtenez une plage. Et bien que (pour continuer la métaphore) si vous cherchez quelqu'un qui peut courir rapidement sur une route de plage, vous ne voulez pas quelqu'un qui sera obsédé par le fait de balayer chaque grain de sable de la route avant de pouvoir commencer à courir, vous voulez quelqu'un qui sera conscient quand il ou elle court inutilement dans des dunes jusqu'aux genoux. Les profileurs ne vous sauveront pas toujours - en termes métaphoriques, ils sont bien meilleurs pour reconnaître un seul gros rocher que vous devez contourner que pour remarquer une multitude de petits grains de sable qui vous embourbent. J'aimerais donc avoir dans mon équipe des personnes qui comprennent ces questions à un niveau fondamental, même si elles font rarement l'effort d'utiliser ces connaissances. N'arrêtez pas d'écrire du code clair dans la quête de la micro-optimisation, mais soyez conscient du genre de choses qui peuvent coûter de la performance, en particulier lors de la conception de vos structures de données, et sachez si vous obtenez une bonne valeur pour le prix que vous payez. C'est pourquoi je pense que c'était une question d'entretien raisonnable, pour explorer la compréhension du candidat sur ces questions.