Initialiser un tableau dans un objet en C ++

Aug 20 2020

J'apprends actuellement le C ++ et j'ai créé une petite classe de tableau.

Problème: je ne peux pas initialiser le tableau dans l'objet avec le constructeur.

De quoi ai-je besoin pour écrire, pour initialiser ce membre? (Je suis sûr que quelque chose avec la syntaxe ne va pas.)

Code:

ary.h:

template<typename T_datatype>
class ary {

private:
    T_datatype* T_dataptr;

public:
    ary<T_datatype>(T_datatype* T_ptr) : T_dataptr(T_ptr) {}
};

main.cpp:

#include "ary.h"

int main()
{
    ary<int> array_int = {2, 3, 4}; //is it something like that?...

    return 0;
}

Réponses

3 RemyLebeau Aug 20 2020 at 22:19

Le constructeur que vous avez implémenté attend un int*pointeur comme entrée, mais {2, 3, 4}ne se décompose pas en un int*, donc non, la syntaxe que vous avez montrée ne fonctionnera pas étant donné la classe que vous avez implémentée jusqu'à présent.

Si vous connaissez la taille exacte du tableau au moment de la compilation, vous pouvez le faire en utilisant à la std::arrayplace:

#include <array>

template<typename T, size_t N>
struct ary {
    std::array<T, N> data;
    ...
};
#include "ary.h"

int main()
{
    ary<int, 3> array_int1{2, 3, 4};

    ary<int, 3> array_int2 = {2, 3, 4};

    ary<int, 3> array_int3 = {{2, 3, 4}};

    return 0;
}

Sinon, si vous voulez vraiment aryavoir un pointeur vers des données de tableau, vous pouvez d'abord déclarer un tableau réel, puis le transmettre au constructeur, par exemple:

template<typename T>
class ary {
private:
    T *dataptr;
    ...

public:
    ary(T* ptr) : dataptr(ptr) {}
    ...
};
#include "ary.h"

int main()
{
    int data[] = {2, 3, 4};
    ary<int> array_int(data);
    ...

    return 0;
};

Mais pensez à donner à votre classe un constructeur qui prend a std::initializer_listcomme entrée à la place, puis demandez à la classe d'allouer son propre tableau en interne (assurez-vous simplement de suivre la règle de 3/5/0 ), par exemple:

#include <algorithm>
#include <utility>

template<typename T>
class ary {
private:
    T *dataptr = nullptr;
    int datasize = 0;

public:
    ary() = default;

    ary(const ary &src)
        : ary()
    {
        if (src.dataptr && src.datasize > 0)
        {
            dataptr = new T[size];
            datasize = src.datasize;
            std::copy(src.dataptr, src.dataptr+src.datasize, dataptr);
        }
    }

    ary(ary &&src)
        : dataptr(src.dataptr), datasize(src.datasize)
    {
        src.dataptr = nullptr;
        src.datasize = 0;
    }

    ary(T* ptr, int size)
        : dataptr(new T[size]), datasize(size)
    {
        std::copy(ptr, ptr+size, dataptr);
    }

    ary(std::initializer_list<T> l)
        : dataptr(new T[l.size()]), datasize(l.size())
    {
        std::copy(l.begin(), l.end(), dataptr);
    }

    ~ary()
    {
        delete[] dataptr;
    }

    ary& operator=(ary rhs)
    {
        std::swap(dataptr, rhs.dataptr);
        std::swap(datasize, rhs.datasize);
        return *this;
    }

    ...
};
#include "ary.h"

int main()
{
    ary<int> array_int1;

    ary<int> array_int2 = {2, 3, 4};

    int data[] = {2, 3, 4};
    ary<int> array_int3{data, 3};

    ary<int> array_int4{array_int2};

    ary<int> array_int5{std::move(array_int3)};

    ...

    return 0;
}

Une meilleure option est d'utiliser à la std::vectorplace et de le laisser faire tout le travail à votre place, par exemple:

#include <vector>

template<typename T>
class ary {
private:
    std::vector<T> data;

public:
    ary() = default;

    // the copy/move constructors, copy/move assignment operators,
    // and destructor will be implicitly generated for you...

    ary(T* ptr, int size) : data(ptr, size) {}
    ary(std::initializer_list<T> l) : data(l) {}

    ...
};
#include "ary.h"

int main()
{
    ary<int> array_int1;

    ary<int> array_int2 = {2, 3, 4};

    int data[] = {2, 3, 4};
    ary<int> array_int3{data, 3};

    ary<int> array_int4{array_int2};

    ary<int> array_int5{std::move(array_int3)};

    ...

    return 0;
}
1 AmirKirsh Aug 20 2020 at 22:01

Le constructeur:

ary<T_datatype> ... 

devrait être nommé simplement:

ary ... 

c'est-à-dire sans le paramètre de modèle.

La ligne en principal:

ary<int> array_int = {2, 3, 4};

attend soit un constructeur qui obtient trois ints, soit un constructeur qui n'obtient std::initializer_list<int>aucun d'eux existe dans votre classe.

AdrianMole Aug 20 2020 at 22:04

Malheureusement, C ++ n'autorise pas les littéraux composés - une fonctionnalité du langage C qui pourrait être utile ici. Au lieu de cela, vous devrez déclarer votre tableau 'argument' au constructeur en tant que variable à part entière, puis le transmettre au constructeur:

int main()
{
//  ary<int> array_int = { 2, 3, 4 }; //is it something like that?...
    int data[] = { 2, 3, 4 };
    ary<int> array_int{ data }; // "data" will here decay into a pointer to its first element

    return 0;
}