Как мне узнать количество char-ов которые выделены с помощью new??
Asked
Active
Viewed 723 times
1 Answers
0
Насколько мне известно (но я могу ошибаться) не существует документированного способа узнать размер динамически выделенного массива по его указателю. Соответственно, возможны следующие варианты:
Вместе с указателем на массив сохранять размер последнего в переменной. Например:
char* pMyArray = new char[NUM_CHARS];int myArrayLen = NUM_CHARS;Следует из (1) - использовать класс-обёртку, представляющий пару "указатель на массив, размер массива". Например, в черновом варианте это может выглядеть так:
template <typename T=char> class CDynamicArray { T* m_pData; int m_length;public: CDynamicArray() { m_pData = nullptr; }
T* Create(int length) { m_pData = new T[length]; m_length = length; return m_pData; } void Delete() { if (m_pData) { delete[] m_pData; m_pData = nullptr; } } T* GetData() { return m_pData; } int GetLength() { return m_length; } ~CDynamicArray() { Delete(); } CDynamicArray(const CDynamicArray&) = delete;};
Не изобретать велосипед, а использовать уже готовое решение
std::vector(https://en.cppreference.com/w/cpp/container/vector).
LShadow77
- 2,157
-
1
-
@KoVadim ну это же черновой вариант. Если не копировать, то вполне рабочий. – LShadow77 Mar 24 '22 at 18:39
-
Скажем так, это ужасный вариант. Вот функция create не нужна. Этим конструктор должен заниматься. А если эту функцию позовут дважды? В деструкторе лишний if и присваивание. – KoVadim Mar 24 '22 at 19:30
-
-
@KoVadim конструктор-то этим может заниматься, однако тут есть один минус: вам не остаётся другого способа создать массив, кроме как при объявлении переменной класса, что бывает далеко не всегда удобно. Вариант с Create/Delete более гибкий (к тому же ничто не мешает добавить второй коструктор, вызывающий
Create()). Насчёт вызова методаCreate()дважды согласен, есть косяк - вариант же черновой. Исправляется с помощью if/assert. "Лишний if" в деструкторе погоды не делает, но от утечки памяти защищает. Хотя в своём коде для этой цели я использую assert, который никогда лишним не бывает)) – LShadow77 Mar 24 '22 at 20:57 -
-
@KoVadim если мы забыли вызвать метод
Delete(), то деструктор его вызовет, и память будет освобождена. Если мы не забыли вызвать методDelete(), то повторный его вызов в деструкторе погоды не сделает. – LShadow77 Mar 24 '22 at 21:06 -
@KoVadim а вообще в деструкторе можно разместить только
assert (m_pData==nullptr);- в этом случае избегаем повторной проверки, однако методDelete()придётся вызывать обязательно... – LShadow77 Mar 24 '22 at 21:11 -
1
-
если m_pData == nullptr, тогда
delete m_pData;работает нормально. Да, там ещё есть бяка. если позватьCreate(...), потомDelete(), а потомGetLength(), то будет неожиданно. – KoVadim Mar 24 '22 at 21:21 -
@KoVadim а не надо звать
Delete(), а потомGetLength(). Ну ёлки-палки, мой пример здесь передаёт только смысл! В допиленном до ума виде он раза в три больше будет и новичка может отпугнуть! – LShadow77 Mar 24 '22 at 21:29 -
-
@LShadow77 исправленный вариант занимает сильно меньше места. а "не нужно звать" - это неверный ответ. Если бы хотя бы зануляли размер... – KoVadim Mar 24 '22 at 21:40
-
@KoVadim я поленился занулить размер, ровно как написать конструктор копирования, вставить проверочные ассерты и директивы условной компиляции для проверки
NDEBUG, добавить перегруженных операторов и методов для удобства в работе. Если исправленный вариант этоstd::vector, то тогда да, меньше места получится)) – LShadow77 Mar 24 '22 at 21:52
std::string,std::vector<char>– KoVadim Mar 23 '22 at 20:54new[]действительно внутри себя вызываетmalloc()и если та возвращаетNULL, бросает исключение. Более того, если выделяется массив классов, содержащих деструктор, то длина массива помещается перед возвращаемым операторомnew[]указателем - т.е., сам указатель на такой массив смещается относительно выделенной области на 4 байта (во всяком случае в g++ так). Подзырено в дизассемблере)) – LShadow77 Mar 24 '22 at 17:20