Utiliser malloc vs new allocateurs en C++

  1. Utiliser le “new” opérateur pour allouer de la mémoire dynamique en C++
  2. Utilisez le new opérateur et std::unique_ptr pour allouer la mémoire dynamique en C++
  3. Utilisez la fonction malloc et realloc/reallocarray pour allouer la mémoire dynamique

Cet article expliquera plusieurs méthodes d’utilisation de malloc par rapport aux new allocateurs en C++.

Utiliser le “new” opérateur pour allouer de la mémoire dynamique en C++

new est l’interface préférée pour gérer directement la mémoire dynamique en C++. Elle construit un objet du type donné et y renvoie le pointeur. Les objets alloués à l’aide de l’opérateur new sont initialisés par défaut, ce qui signifie que les objets de type intégré et composé ont des valeurs de déchets qui doivent être initialisées avant utilisation.

Notez que new peut être appelé avec plusieurs notations pour répondre à différents besoins, mais dans l’exemple suivant, nous allouons le tableau int de taille 10. Ainsi, le pointeur retourné stocké dans la variable arr1 pointe vers le bloc de mémoire de 40 octets. La fonction initPrintIntVector n’est implémentée que pour mieux démontrer un exemple pratique de codage. Puisque nous utilisons un pointeur dit nu, il est important de libérer la mémoire allouée avec l’opérateur delete avant que le programme ne se termine. Cependant, les crochets après l’opérateur delete sont également nécessaires pour désallouer chaque emplacement dans le tableau.

#include <iostream>
#include <vector>
#include <iomanip>
#include <random>

using std::cout; using std::vector;
using std::endl; using std::setw;

constexpr int SIZE = 10;
constexpr int NEW_SIZE = 20;
constexpr int MIN = 1;
constexpr int MAX = 1000;

void initPrintIntVector(int *arr, const int &size)
{
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_int_distribution<int> distr(MIN, MAX);

    for(int i = 0; i < size; ++i) {
        arr[i] = distr(eng) % 1000;
        cout << setw(2) << arr[i] << "; ";
    }
    cout << endl;
}

int main()
{
    int *arr1 = new int[SIZE];

    initPrintIntVector(arr1, SIZE);

    delete [] arr1;
    return EXIT_SUCCESS;
}

Sortie (*aléatoire) :

 8; 380; 519; 536; 408; 666; 382; 244; 448; 165;

Utilisez le new opérateur et std::unique_ptr pour allouer la mémoire dynamique en C++

Même si le new opérateur semble être un bon outil pour l’allocation dynamique de la mémoire, il peut être très sujet à des erreurs dans les grandes bases de données avec des manipulations intensives de la mémoire. En effet, l’allocation des ressources mémoire au bon moment est un problème assez difficile à résoudre, et il se traduit le plus souvent par des fuites de mémoire ou des erreurs d’exécution inattendues. C’est pourquoi la bibliothèque standard, depuis la version C+11, a ajouté des pointeurs intelligents qui effacent automatiquement la mémoire vers laquelle ils pointent. std::unique_ptr est un type de pointeurs intelligents, qui se permet seulement de pointer vers l’objet donné. Notez que l’allocation est toujours faite en utilisant le new opérateur, et après que le pointeur ait été utilisé, nous pouvons quitter le programme sans appeler delete.

#include <iostream>
#include <vector>
#include <iomanip>
#include <random>

using std::cout; using std::vector;
using std::endl; using std::setw;

constexpr int SIZE = 10;
constexpr int NEW_SIZE = 20;
constexpr int MIN = 1;
constexpr int MAX = 1000;

void initPrintIntVector(int *arr, const int &size)
{
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_int_distribution<int> distr(MIN, MAX);

    for(int i = 0; i < size; ++i) {
        arr[i] = distr(eng) % 1000;
        cout << setw(2) << arr[i] << "; ";
    }
    cout << endl;
}

int main()
{
    std::unique_ptr<int[]> arr2(new int[SIZE]);

    initPrintIntVector(arr2.get(), SIZE);

    return EXIT_SUCCESS;
}

Production :

985; 885; 622; 899; 616; 882; 117; 121; 354; 918;

Utilisez la fonction malloc et realloc/reallocarray pour allouer la mémoire dynamique

D’autre part, le code C++ peut appeler la fonction d’allocation originale de style C - malloc, ce qui est une manière assez archaïque de manipulation dynamique de la mémoire pour les normes C++ modernes. Ce n’est pas la façon recommandée d’allouer les objets sur le tas, mais du côté positif, malloc offre une fonctionnalité plus flexible.

malloc est appelé avec un seul argument qui spécifie la sizeof de l’objet et renvoie le void * qui doit être attribué au type correspondant en C++. Le seul avantage de la mémoire allouée à malloc est qu’elle peut être étendue/réduite par la fonction realloc ou reallocarray. La fonction realloc prend le pointeur vers l’objet et la nouvelle taille comme arguments, alors que reallocarray prend le pointeur, le nombre d’éléments, et la taille de chaque élément. Notez que si la mémoire de l’objet est étendue, les anciennes valeurs stockées restent intactes, et les éléments nouvellement ajoutés ne sont pas initialisés. Ainsi, l’exemple suivant imprime les éléments arr3 développés uniquement à des fins de démonstration, et cela ne devrait pas être le cas dans le programme du monde réel.

#include <iostream>
#include <vector>
#include <iomanip>
#include <random>

using std::cout; using std::vector;
using std::endl; using std::setw;

constexpr int SIZE = 10;
constexpr int NEW_SIZE = 20;
constexpr int MIN = 1;
constexpr int MAX = 1000;

void initPrintIntVector(int *arr, const int &size)
{
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_int_distribution<int> distr(MIN, MAX);

    for(int i = 0; i < size; ++i) {
        arr[i] = distr(eng) % 1000;
        cout << setw(2) << arr[i] << "; ";
    }
    cout << endl;
}

void printIntVector(int *arr, const int &size)
{
    for(int i = 0; i < size; ++i) {
        cout << setw(2) << arr[i] << "; ";
    }
    cout << endl;
}

int main()
{
    int *arr3 = static_cast<int *>(malloc(SIZE * sizeof(int)));
//    int *arr3 = static_cast<int *>(malloc(SIZE * sizeof *arr3));
//    int *arr3 = static_cast<int *>(malloc(sizeof(int[SIZE])));

    initPrintIntVector(arr3, SIZE);

    arr3 = static_cast<int *>(reallocarray(arr3, NEW_SIZE, sizeof(int)));
    // arr3 = static_cast<int *>(realloc(arr3, NEW_SIZE * sizeof(int)));
    printIntVector(arr3, NEW_SIZE);

    free(arr3);
    return EXIT_SUCCESS;
}

Production :

128; 346; 823; 134; 523; 487; 370; 584; 730; 268;
128; 346; 823; 134; 523; 487; 370; 584; 730; 268;  0;  0;  0;  0;  0;  0;  0;  0;  0;  0;