Copie

La première question à se poser

Dans le code C++, il faut faire attention au signe = en se posant la question :

Que se passe-t-il lorsqu’on écrit : A = B ?

Dans tous les cas, la variable A va contenir une information identique à la variable B. Cependant, deux scénarios peuvent se produire :

  • Soit la variable A est une copie indépendante de la variable B et ces deux variables vont évoluer séparément dans le programme : toute action ou modification de l’une ne se reportera pas sur l’autre.

  • Soit la variable A est une référence à la variable B et, dans ce cas, elle est juste un alias vers la variable B : lorsque l’on utilise le nom A, on manipule en fait la variable originale B.

Note

Il existe un troisième scénario où la variable A est une copie partielle de la variable B. Dans ce cas, certains éléments de la variable A sont des copies et d’autres des références. A notre niveau, nous éviterons cette situation car elle est source de nombreux bugs.

La réponse à cette question n’est pas immédiate car elle dépend fortement du contexte et notamment du type de A et de B. Nous allons dans la suite examiner différents scénarios en les testant par des exemples.

Comportement pour les affectations

Pour les types fondamentaux

Veuillez exécuter le code suivant dans votre environnement préféré, puis analysez les affichages.

#include <iostream>

int main()
{
        // type entier
        int a = 10;
        int b = a;
        b++;
        std::cout << a << " " << b << std::endl;

        // type double
        double c = 5;
        double d = c;
        d++;
        std::cout << c << " " << d << std::endl;

        // type bool
        double e = true;
        double f = e;
        f = !f;
        std::cout << e << " " << f << std::endl;
}

Pour chaque type testé, indiquez si l’affirmation correspondante est vraie ou fausse :

L’affectation sur des variables de type entier produit une copie.

L’affectation sur des variables de type double produit une copie.

L’affectation sur des variables de type booléen produit une copie.

Pour les structures

Examinons maintenant le type structure. Veuillez exécuter le code suivant dans votre environnement préféré, analysez ensuite les affichages.

#include <iostream>

struct v
{
    int x;
    int y;
};

int main()
{
        // type structure
        v B;
        B.x = 10;
        B.y = 20;

        v A;
        A = B;   // le cas qui nous intéresse

        A.x += 5;
        A.y += 5;

        // les affichages

        std::cout <<B.x << " " << B.y << std::endl;
        std::cout <<A.x << " " << A.y << std::endl;

}

Indiquez si l’affirmation suivante est vraie ou fausse :

L’affectation sur des variables de type structure produit une copie.

Passage de paramètres

Cas des types fondamentaux

Le passage d’un argument à une fonction peut soit déclencher une copie soit mettre en place une référence. Nous allons donc vérifier ce qu’il se passe en exécutant le code suivant et en analysant les résultats.

#include <iostream>

void F(int a, double b, bool c)
{
    std::cout << "Entrée de fonction : " << a << " " << b << " " << c << std::endl;
        a += 1;
        b += 1;
        c = !c;
    std::cout << "Sortie de fonction : " << a << " " << b << " " << c << std::endl;
}

int main()
{
        // type entier
        int    a = 10;
        double b = 20.0;
        bool   c = true;
        std::cout << "Avant l'appel      : " << a << " " << b << " " << c << std::endl;
        F(a,b,c);
        std::cout << "Après l'appel      : " << a << " " << b << " " << c << std::endl;
}

Pour chaque type testé, indiquez si l’affirmation correspondante est vraie ou fausse :

Le passage de paramètres avec un type entier produit une copie.

Le passage de paramètres avec un type double produit une copie.

Le passage de paramètres avec un type booléen produit une copie.

Cas des structures

Le langage a-t-il voulu rester dans la logique des comportements précédents ou a-t-il choisi une autre stratégie ? Veuillez exécuter le code suivant, puis analysez les résultats.

#include <iostream>

struct v
{
    int x;
    int y;
};

void F(v a)
{
    std::cout << "Entrée de fonction : " << a.x << " " << a.y << std::endl;
        a.x += 1;
        a.y += 2;
    std::cout << "Sortie de fonction : " << a.x << " " << a.y << std::endl;
}

int main()
{
        // type structure
        v a;
        a.x = 10;
        a.y = 20;

        std::cout << "Avant l'appel      : " << a.x << " " << a.y << std::endl;
        F(a);
        std::cout << "Après l'appel      : " << a.x << " " << a.y << std::endl;
}

Indiquez si l’affirmation suivante est vraie ou fausse :

Le passage de paramètres avec un type structure produit une copie des informations contenues dans la structure.

Conclusion

Suite à nos tests, nous constatons que le C++ a choisi d’avoir un comportement homogène pour l’affectation et le passage d’arguments et ceci pour l’ensemble des types testés. En résumé, nous pouvons conclure par :

REGLE : En C++, l’affectation et le passage d’arguments se font toujours par copie aussi pour les types fondamentaux que pour les structures.