Элементы массивов в куче против int a[n]

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Аватара пользователя
Сионист
Сообщения: 1077
Зарегистрирован: 31 мар 2014, 06:18

03 апр 2017, 14:53

Формально нет ни каких запретов на

Код: Выделить всё

size_t n;
std::cin>>n;
int a[n];
: к тому моменту, когда исполнение доберётся до декларации

Код: Выделить всё

int a[n];
n уже известно и можно увеличить стек на размер массива и потом учесть в адресах следующих локальных переменных. Но обратите внимание: стек увеличивается на неизвестную на этапе разработки величину, что не есть хорошо, так как не позволяет адекватно настроить максимальный размер стека. Рекурсия страдает тем же самым, но иногда просто нет другого выхода, кроме как использовать рекурсию. К тому же есть ведь ещё хвостовая рекурсия, она этим не страдает. Такому же массиву альтернатива есть всегда. На этапе разработки n не известно, а суммарный размер локальных переменных, хоть тест этого и не показывает, должен быть известен на этапе разработки, так как только так можно обеспечить предсказуемый расход стека, а он дефицитнее кучи. Опасность указателей - полумиф, опасны лишь те указатели, которые выдаются наружу. А внутри одного проекта программист уж точно знает, где у него какой указатель валяется и с чем его "едят". Даже если программистов много и один указатель декларировал, другой присвоил, третий передал внутри проекта, четвертый использует. Всё равно. Это такая же переменная, как какой нибудь инт. В интах ни кто не путается? Чем же указатели хуже? Не знаешь - не трогай, трогаешь - узнай, не можешь - не программируй. И ни каких утечек памяти из указателей не вытекает. Я программирую с весны 1995-го года и до сих пор не смог получить утечку памяти. Видимо для этого как раз и нужны умные указатели, или странные то ли указатели то ли ссылки. В любую же функцию, или оператор массив в любом случае именно как указатель и передаётся. Не нравится, когда указатель валяется на самом виду? Ну инкапсулируйте. В чём проблема? Тогда автор класса будет полностью отвечать за все операции с указателем, количество кривых рук с допуском к указателю резко сократится. Вы же этого хотите? При

Код: Выделить всё

size_t n;
std::cin>>n;
int a[n];
же это как раз не достигается, указатель будет лишь слегка прикрыт граблями. Причём, стеклянными.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

03 апр 2017, 17:27

А можно небольшую просьбу? Можно писать по сути? Я пока дочитал, чуть не вывихнул челюсть во время затяжных зеваний. И, кстати, так и не нашёл вопроса. В чём вопрос?
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Сионист
Сообщения: 1077
Зарегистрирован: 31 мар 2014, 06:18

03 апр 2017, 17:55

Romeo писал(а):И, кстати, так и не нашёл вопроса
А я его и не задавал.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

03 апр 2017, 18:19

Тогда я не вижу смысла в создании темы.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Skwoogey
Сообщения: 63
Зарегистрирован: 11 янв 2016, 02:25

05 апр 2017, 00:17

Код: Выделить всё

void actual_main(int *mas)
{
	/*
	some code
	*/
}

int main()
{
	int n;
	cin << n;
	switch(n)
	{
		case 1:
		{
			int mas[1];
			actual_main(mas);
			break;
		}
		case 2:
		{
			int mas[2];
			actual_main(mas);
			break;
		}
		/*
		more
		*/
		case N:
		{
			int mas[N];
			actual_main(mas);
			break;
		}
		default:
		{
			cout << "bad size";
		}
	}
	return 0;
}
знаю, что плохая идея, но я так делал иногда, пока не узнал о динамическом определении.
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

05 апр 2017, 01:27

Это ужасное решение. Все современные компиляторы уже позволяют делать так:

Код: Выделить всё

size_t n;
std::cin>>n;
int a[n];
Муру от Сиониста не читай. Это единственное правильное решение для подобного случая.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Skwoogey
Сообщения: 63
Зарегистрирован: 11 янв 2016, 02:25

05 апр 2017, 10:30

Такая вещь только с size_t прокатит? или можно с подобными типами?
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

05 апр 2017, 11:20

Любой целочисленный тип.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить