Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 14.05.2019, 09:50   #1
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,544
По умолчанию От куда оператор delete берет размер массива, чтобы освободить всю память, которая была выделена под массив?

Возник вот какой вопрос. Допустим, пользователь задает число элементов и мы создаем массив динамически:
Код:
int n;
cin>>n;
int * a=new int[n];
Для того, чтобы провести какие-либо манипуляции с массивом, в функцию надо передать ссылку на массив и его размер. Скажем, заголовок функции вывода элементов массива на экран может выглядеть так:
Код:
void array_write(int a[], int n)
Но удаление массива осуществляется без указания размера:
Код:
delete [] a;
От куда оператор delete берет размер массива, чтобы освободить всю память, которая была выделена под массив? Можно ли как-то получить доступ к этой информации, чтобы не передавать в функции размер массива? То есть функцию вывода объявить так:
Код:
void array_write(int a[])
А уже внутри тела функции получить n - размер массива.
Arigato вне форума Ответить с цитированием
Старый 14.05.2019, 10:41   #2
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

погуглил. на stackoverflow много про это.
короче.
a - это не массив, это указатель.
delete знает, сколько выделено памяти (берёт из соответствующей структуры).

по нормальному нужно в C++ использовать std:vector() вместо указателя на массив.

как хакерский вариант, есть такое решение:
Цитата:
Well there is actually a way to determine the size, but it's not "safe" and will be diferent from compiler to compiler.... so it shouldn't be used at all.

When you do: int* arr = new int[256];

The 256 is irrelevant you will be given 256*sizeof(int) assuming for this case 1024, this value will be stored probably at ( arr - 4 )

So to give you the number of "items"

Код:
int* p_iToSize = arr - 4;

printf("Number of items %d", *p_iToSize / sizeof(int));
For every malloc, new, whatever before the continuos memory block that you receive, there is also allocated a space reserved with some information regarding the block of memory you were given.
Но это грязный хак и зависит от компилятора (и от его опций).


Так что, передавайте n и не парьтесь!
Serge_Bliznykov вне форума Ответить с цитированием
Старый 14.05.2019, 15:08   #3
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,544
По умолчанию

Получается, что размер массива фактически находится как бы в -1 элементе. Чем-то напоминает паскалевские строки, где размер строки хранится в нулевом символе. Странно, что нет стандартной функции определения размера массива, если это можно сделать достаточно просто и это делается при вызове delete.
Arigato вне форума Ответить с цитированием
Старый 14.05.2019, 15:14   #4
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

В С++ лучше использовать подходящий контейнер, а не так.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 15.05.2019, 00:42   #5
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Цитата:
Сообщение от Arigato Посмотреть сообщение
Странно, что нет стандартной функции определения размера массива
Это уходит корнями еще в С - там тоже отсутствуют средства получения размера выделенного блока. Далеко не всегда нужно знать размер, а если стандарт будет вас заставлять его хранить, то это уже лишний overhead.
Соответственно new/delete выкручиваются сами как могут, но стандарт опять же не заставляет их хранить размер именно в -1 элементе. Компилятор волен использовать любую другую схему.

Скорость - наше все.
Если вы пишете на С++ и используете напрямую new, delete и * то значит у вас (большие) проблемы.
waleri вне форума Ответить с цитированием
Старый 22.05.2019, 13:25   #6
taras-proger77
Заблокирован
 
Регистрация: 17.12.2018
Сообщений: 514
По умолчанию

Цитата:
Сообщение от Arigato Посмотреть сообщение
Получается, что размер массива фактически находится как бы в -1 элементе. Чем-то напоминает паскалевские строки, где размер строки хранится в нулевом символе. Странно, что нет стандартной функции определения размера массива, если это можно сделать достаточно просто и это делается при вызове delete.
Это не языкастая функция, а то ли системная, то ли транслятора. И не факт, что она знает размер элемента. Вот должна ли она быть доступна каждому приложению – отдельный вопрос. И кто ж мешает вложить размер в класс, в него же завернуть динамический массив, а передавать по ссылке, или по константной ссылке?

Последний раз редактировалось taras-proger77; 22.05.2019 в 18:22.
taras-proger77 вне форума Ответить с цитированием
Старый 03.06.2019, 01:06   #7
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,544
По умолчанию

Со статическими массивами можно узнать размер. Но если массив передать в функцию (а передаются они как указатели), то размер уже не узнать:

Код:
#include <cstdlib>
#include <iostream>

using namespace std;

void func(int A[]){
	cout<<"FUNC: "<<sizeof(A)/sizeof(A[0])<<endl;
}

int main()
{
	int A[]={1,2,3,4,5,6,7,8,9,0};
	cout<<"MAIN: "<<sizeof(A)/sizeof(A[0])<<endl;
	func(A);
	return 0;
}
Arigato вне форума Ответить с цитированием
Старый 03.06.2019, 14:11   #8
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Цитата:
Сообщение от Arigato Посмотреть сообщение
Со статическими массивами можно узнать размер. Но если массив передать в функцию
Не совсем понял - это утверждение или вопрос?

Формально в С++ 11 можно сделать шаблонную функцию/метод куда будет передаваться ссылка на массив с размером, но это только для статических массивов.
Строго говоря, в С/С++ нет массивов, все делается через указатели, т.е. размер нужно передавать самому. Квадратные скобки это скорее выделение памяти.
waleri вне форума Ответить с цитированием
Старый 03.06.2019, 15:29   #9
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 15,544
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Не совсем понял - это утверждение или вопрос?
Это комментарий к примеру кода ниже.

Цитата:
Сообщение от waleri Посмотреть сообщение
размер нужно передавать самому
Вопрос темы не в том, нужно или нет передавать размер, а в том, что оператор delete [] сам узнает размер, ему ничего передавать не надо.
Arigato вне форума Ответить с цитированием
Старый 04.06.2019, 12:24   #10
Dekay
Пользователь
 
Регистрация: 21.06.2016
Сообщений: 65
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Если вы пишете на С++ и используете напрямую new, delete и * то значит у вас (большие) проблемы.
Ну-ка. Почему это?
Dekay вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как освободить память от типа Audio? reyn90 Общие вопросы .NET 6 26.12.2015 23:21
Освободить память формы st_yak C++ Builder 0 21.12.2013 19:56
Проверить выделена ли память под объект Sibedir Общие вопросы Delphi 58 21.03.2011 11:48
Освободить память от CEdit Eros Общие вопросы C/C++ 0 29.11.2010 15:37
Неправильно выделена память. С++ Purr Помощь студентам 7 31.10.2010 20:05