[C++] Je ne comprends pas très bien cette syntaxe

a marqué ce sujet comme résolu.

Bonjour,

Pourquoi le code suivant affiche-t-il le message « OK » ?
Selon moi, ligne 18, on alloue un emplacement pour l’objet Entier, mais sans forcément le construire.

#include <iostream>

using std::cout;
using std::endl;

class Entier {
    public :
    Entier() {
        cout << "OK" << endl;
    }
    int value;
};

int main() {
    Entier test;
    return 0;
}

C’est aussi choquant que si vous me disiez qu’on a un nouvel objet entier créé en mémoire avec ce code :

int maVariable;

Pour moi, on alloue la mémoire dont on a besoin, sans la remplir.

Salut,

C’est aussi choquant que si vous me disiez qu’on a un nouvel objet entier créé en mémoire avec ce code :

int maVariable;

Ben euh je sais pas à quoi tu t’attends mais là tu demandes littéralement à créer un int, de la même façon que tu demandes à créer un Entier avec l’autre code. Sa valeur est non-définie, mais elle existe. En général, la valeur prise est celle du contenu pré-existant de l’emplacement mémoire pris par ton int.

+0 -0

Bonjour

Le type int est un du compilateur. Si tu l’initialises comme tu l’as écrit, c’est un UB et il peut avoir n’importe quel valeur. En revanche lorsque tu as un objet avec un constructeur sans arguments (ou avec des arguments avec valeur par défaut (Entier(int v = 5) {})), le standard dit que l’objet, dans un appel comme Entier test; est construit (je n’ai pas la réf exacte dans le dit standard en revanche).

En Java, toutes les variables non primitives (les objets, pas les types primitifs comme int, boolean, …) sont des pointeurs.
Tu as une abstraction mémoire qui fait que tu ne manipules jamais d’objet directement.

Le C++ est issue du C où tu n’as qu’une très faible abstraction mémoire, la plus petite possible. Quand tu manipules un MonObjet, c’est vraiment un MonObjet. Pas un pointeur sur ce MonObjet.

Ce qui fait que quand tu crées une variable de type Objet, elle appele forcément le constructeur.

Si tu l’initialises comme tu l’as écrit, c’est un UB et il peut avoir n’importe quel valeur.

Ce n’est pas la non initialisation qui est un UB, c’est d’utiliser une variable non initialisée. Assigné une variable non initialisée est un code totalement bien défini.

+0 -0

En fait, la confusion vient de la différence entre allouer un espace mémoire pour y placer plus tard un entier, et remplir cet espace mémoire avec un entier.

Toujours en C, voici comment j’interprète le programme suivant :

int main(void)
{
    int a;
    a = 42;

    return 0;
}

Ligne 3

On alloue un espace mémoire (de taille sizeof(int) octets) et on lui affecte une adresse mémoire, afin de pouvoir retrouver cet emplacement.

Comme l’espace mémoire est créé sur la pile, selon le post de @Pataques, la variable a n’est pas initialisée et il vaut mieux éviter de lire son contenu, puisqu’il ne nous appartient pas. Aucun entier n’a été créé, on a juste alloué de la mémoire.

Ligne 4

Le membre de droite de l’expression créé un entier, en faisant appel au constructeur new int() implicitement. Cet entier, considérons-le comme un objet, est alors placé dans l’espace mémoire précédemment alloué.

A cette étape, le constructeur est donc appelé.

Bref, c’est pourquoi je pense que Entier entier; ne devrait pas faire appel au constructeur, mais pourquoi ai-je tort dans le raisonnement précédent ?

Humm, ce n’est pas comme ça que ça fonctionne.

Quand tu aloues un espace mémoire, tu réserves cet espace. Et c’est tout. Si ça marche, tu as le droit de l’utiliser, il t’appartient.

Ce qui fait que le constructeur de Entier est appelé lorsque tu écris :

Entier entier;

C’est le RAII Ressource Acquisition is initialization. C’est une technique ingénieuse de gestion de la mémoire.

C’est cohérent avec le langage. new Entier() on aloue un Entier sur le tas. On y accède avec un pointeur.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte