2017-10-16 1 views
2
#include <iostream> 
using namespace std; 

template <class T> 
void swap1(T& a, T& b) { 
    T c = a; 
    a = b; 
    b = c; 
} 

int main() { 
    int n1 = 5; 
    int n2 = 7; 
    swap1(n1, n2); 
    cout << n1 << " " << n2 << endl; 

    int *p1 = &n1; 
    int *p2 = &n2; 
    swap1(*p1, *p2); 
    cout << n1 << " "<< n2 << endl; 
} 

Dans de nombreux langages, lorsque vous appelez une fonction, vous évaluez d'abord ses arguments, puis vous appliquez la fonction aux résultats de l'évaluation.Évaluation d'une fonction avec les paramètres de référence

Si nous suivons cette règle ici cependant, swap1(n1, n2) et swap1(*p1, *p2) évalueraient tous les deux à swap1(5, 7) ce qui n'a aucun sens. Alors, quelles sont les règles d'évaluation dans ce cas-ci? Aussi, quelles sont les règles d'évaluation d'une fonction en général en C++?

+0

A l'intérieur de la fonction, les arguments 'a' et' b' *** font référence aux variables * * n1' et 'n2' de la fonction' main'. Vous ne passez pas dans les * valeurs * de ces variables. Peu importe que vous utilisiez des pointeurs déréférencés, puisque ces pointeurs pointent sur 'n1' et' n2'. –

+0

Considérons une opération comme 'int n = 2; n ++; 'Vas-tu insister pour dire que c'est équivalent à' 2 ++ '...? Astuce: étudier les différences entre les valeurs l et les valeurs r, connues depuis les débuts de C. – CiaPan

+1

L'évaluation d'une lvalue ne signifie PAS accéder à la valeur stockée; le résultat de l'évaluation de '* p1' est un désignateur de cet emplacement de mémoire, pas' 5'. Ensuite, lorsque les paramètres de la fonction sont initialisés: l'effet d'initialiser un paramètre de référence avec une expression lvalue est de lier la référence à l'expression (encore une fois, n'accède pas à l'emplacement de la mémoire) –

Répondre

2

Dans de nombreuses langues, lorsque vous appelez une fonction, vous évaluez d'abord ses arguments, puis vous appliquez la fonction aux résultats de l'évaluation.

C'est exactement ce qui se passe aussi en C++. Cependant, nous devons analyser ce que signifie «évaluer les arguments d'une fonction». En C++, cela signifie "copier-initialiser le paramètre en utilisant l'expression spécifiée comme argument". Le moyen de copier-initialiser une référence C++ consiste à lier à l'entité définie par l'initialiseur. Dans le cas de références lvalues ​​(comme dans votre swap), cela signifie que l'initialiseur doit être une lvalue. n1 est une lvalue, tout comme *p1. Puisque la référence veut une valeur, c'est toute l'évaluation à faire.

Si le paramètre était de type valeur (pas une référence), la conversion de lvalue en valeur serait appliquée après l'initialisation de la valeur. Mais puisque nous initialisons une référence, cette conversion ne se produit pas.