Инициализация массива в объекте в C ++
В настоящее время я изучаю 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;
}
Ответы
Реализованный вами конструктор ожидает int*
указатель в качестве входных данных, но {2, 3, 4}
не распадается на него 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;
}
Конструктор:
ary<T_datatype> ...
следует называть просто:
ary ...
т.е. без параметра шаблона.
Строка в основном:
ary<int> array_int = {2, 3, 4};
ожидает либо конструктор, который получает три int
s, либо конструктор, у которого std::initializer_list<int>
ни один из них не существует в вашем классе.
К сожалению, 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;
}