การเริ่มต้นอาร์เรย์ในวัตถุใน C ++

Aug 20 2020

ฉันกำลังเรียนรู้ C ++ และฉันสร้างอาร์เรย์คลาสขึ้นมา

ปัญหา: ฉันไม่สามารถเริ่มต้นอาร์เรย์ในวัตถุด้วยตัวสร้าง

ฉันต้องเขียนอะไรเพื่อเริ่มต้นสมาชิกนี้? (ฉันแน่ใจว่ามีบางอย่างที่มีไวยากรณ์ไม่ถูกต้อง)

รหัส:

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;
}

คำตอบ

3 RemyLebeau Aug 20 2020 at 22:19

ตัวสร้างที่คุณติดตั้งคาดว่าint*ตัวชี้จะเป็นอินพุต แต่{2, 3, 4}จะไม่สลายตัวเป็น an int*ดังนั้นไม่เลยไวยากรณ์ที่คุณแสดงจะใช้ไม่ได้กับคลาสที่คุณได้นำไปใช้จนถึงตอนนี้

หากคุณทราบขนาดอาร์เรย์ที่แน่นอนในเวลาคอมไพล์คุณสามารถทำได้โดยใช้std::array:

#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;
}

มิฉะนั้นหากคุณต้องการaryมีตัวชี้ไปยังข้อมูลอาร์เรย์จริงๆคุณสามารถประกาศอาร์เรย์จริงก่อนจากนั้นจึงส่งต่อไปยังตัวสร้างเช่น:

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;
};

แต่พิจารณาให้คลาสของคุณเป็นตัวสร้างที่รับstd::initializer_listอินพุตเป็นแทนจากนั้นให้คลาสจัดสรรอาร์เรย์ของตัวเองภายใน (เพียงแค่ปฏิบัติตามกฎ 3/5/0 ) เช่น:

#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;
}

ตัวเลือกที่ดีกว่าคือใช้std::vectorแทนและปล่อยให้มันทำงานทั้งหมดให้คุณเช่น:

#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

ตัวสร้าง:

ary<T_datatype> ... 

ควรตั้งชื่อง่ายๆว่า:

ary ... 

คือไม่มีพารามิเตอร์เทมเพลต

บรรทัดในหลัก:

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

คาดหวังว่าคอนสตรัคเตอร์ที่ได้รับสามints หรือคอนสตรัคเตอร์ที่std::initializer_list<int>ไม่มีอยู่ในคลาส

AdrianMole Aug 20 2020 at 22:04

น่าเสียดายที่ C ++ ไม่อนุญาตให้ใช้อักษรผสมซึ่งเป็นคุณลักษณะของภาษา C ที่อาจมีประโยชน์ที่นี่ แต่คุณจะต้องประกาศอาร์เรย์ของคุณ 'อาร์กิวเมนต์' ให้กับตัวสร้างเป็นตัวแปรในสิทธิ์ของมันเองจากนั้นส่งต่อไปยังตัวสร้าง:

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;
}