Russian Qt Forum
Ноябрь 26, 2024, 19:11 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 ... 3 4 [5] 6   Вниз
  Печать  
Автор Тема: Плюсолюбителям  (Прочитано 43087 раз)
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #60 : Март 14, 2015, 17:08 »

Потому, что это избыточно.
Вы выделяете память сами, вы знаете ее размер, вы знаете начало блока, вы можете вычислить конец блока.
Если вам нужно иметь возможность по указателю, получить размер блока, вы всегда это можете реализовать сами.
Записан
AzazelloAV
Гость
« Ответ #61 : Март 15, 2015, 01:46 »

Потому, что это избыточно.
Вы выделяете память сами, вы знаете ее размер, вы знаете начало блока, вы можете вычислить конец блока.
Если вам нужно иметь возможность по указателю, получить размер блока, вы всегда это можете реализовать сами.

Наоборот, избыточно хранить данные "самому". Вместо того, чтобы мы обратились "к объекту", приходится самому вычислять.

Давайте если уж так, сравним на более примитивном уровне.
Возьмём "нелюбимый" всеми pascal с его хранением длины строки в первом байте и Си, с заканчивающим нулём (я про то далёкое).

Паскалевская строка самодостаточна (опустим возражения, что классический паскаль только 255 размер), сишная тупа, нужно искать 0. На данном этапе рожки да ножки остались от сишных строк, все пользуются "паскалевским" типом строк (к примеру   QString т.е. все заранее знают, каков размер.)

Если вы поняли, я провожу аналогию - все знают, что строки с #0 плохо, но все понимают, почему так.  

У меня нет объяснений про new/delete.

P.S. Только не надо говорить про класс QString, что это не паскаль строка и рядом не стояла. Мы с другой позиции смотрим.
« Последнее редактирование: Март 15, 2015, 01:50 от AzazelloAV » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #62 : Март 15, 2015, 10:38 »

Паскалевская строка самодостаточна (опустим возражения, что классический паскаль только 255 размер), сишная тупа, нужно искать 0. На данном этапе рожки да ножки остались от сишных строк, все пользуются "паскалевским" типом строк (к примеру   QString т.е. все заранее знают, каков размер.)
Всегда есть конфликт между эффективностью и удобством пользования, это нормально.
Код
C++ (Qt)
s2 = s1 + ".txt";
Да, с сишной строкой это отольется в порядочный геморрой. Но ведь за удобство и заплачено немало. Сначала надо привести ".txt" к строковому классу, выделить память и скопировать. А с QString еще и в юникод перевести. Потом опять выделить память и склеить строки. Потом еще раз скопировать в s2. И наконец избавиться от временных переменных.

Популярное мнение "да зачем мне знать что там делается за кадром? Я вот написал 1 строку - и все! Что я, должен с strcpy мудохаться?". Нет конечно, к этому никто не призывает. Но понимать что чего стоит необходимо. Иначе бездумный подход само-воспроизводится, "невникающий" начинает ляпать контейнерами - а это уже совсем не мелочи со строками. Вот не так уж давно человек накатал статью(!) где предлагает такой способ создания 2-мерного массива
Код
C++ (Qt)
std::vector <std::vector <int> > MyArray
Это взамен "устаревшего" С-массива. Ну а чего? Где говнокод? Удобно писать MyArray[ i ][ j ]? Удобно! Ну и все!

Короче: не нравится ассеиблер - переходите на жабу, будете всем в нос тыкать "сборщиком мусора" и.т.п.  Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #63 : Март 15, 2015, 11:00 »

У меня нет объяснений про new/delete.
А какие претензии к new/delete? Они выделяют/освобождают необходимый блок памяти. Все.
Вы же хотите, что бы указатель знал размер блока, внутрь которого он указывает. Вот это и есть избыточность, которая никому не нужна.
Мне нужно, что бы указатель был просто адресом в пространстве процесса. Если мне понадобятся какие-то дополнительные параметры, я их обеспечу сам. А если все указатели будут хранить какие-то размеры, то мы получим огромный оверхед как по памяти, так и по производительности. Понадобится эти размеры вычислять и заполнять, для всех указателей.
Записан
AzazelloAV
Гость
« Ответ #64 : Март 15, 2015, 13:33 »

У меня нет объяснений про new/delete.
А какие претензии к new/delete? Они выделяют/освобождают необходимый блок памяти. Все.
Вы же хотите, что бы указатель знал размер блока, внутрь которого он указывает. Вот это и есть избыточность, которая никому не нужна.
Мне нужно, что бы указатель был просто адресом в пространстве процесса. Если мне понадобятся какие-то дополнительные параметры, я их обеспечу сам. А если все указатели будут хранить какие-то размеры, то мы получим огромный оверхед как по памяти, так и по производительности. Понадобится эти размеры вычислять и заполнять, для всех указателей.


Да какой же оверхед. Это что, колодец какой то бездонный (черный ящик) ,  ну знает же кто-то сколько памяти нужно освободить при делете, это где то хранится, в любом случае это где то есть, ну что у нас делете  - это какое то запредельное что-то, которое живет в секретном потоке на секретном процессоре? Он что то вызывает и это что-то уж точно знает что оно делает и сколько нужно удалить.  Значит данные уже гдето "живут". А у нас получается, что создать/удалить объект (объект ООП) мы запросто можем, а узнать сколько он памяти ест - тут целые програмные комплексы нужны.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #65 : Март 15, 2015, 14:09 »

ну знает же кто-то сколько памяти нужно освободить при делете
Знает и что? Как этот размер должен быть связан с любым указателем, который вы можете передать в функцию?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #66 : Март 15, 2015, 14:13 »

Да какой же оверхед. Это что, колодец какой то бездонный (черный ящик) ,  ну знает же кто-то сколько памяти нужно освободить при делете, это где то хранится, в любом случае это где то есть, ну что у нас делете  - это какое то запредельное что-то, которое живет в секретном потоке на секретном процессоре? Он что то вызывает и это что-то уж точно знает что оно делает и сколько нужно удалить.  Значит данные уже гдето "живут". А у нас получается, что создать/удалить объект (объект ООП) мы запросто можем, а узнать сколько он памяти ест - тут целые програмные комплексы нужны.
Вы как-то уперлись в это "delete ЗНАЕТ размер". Ну знает, так что, давайте чтобы каждый указатель знал свой размер? Ну это, мягко говоря, неразумно. Уже не раз сказали что указатель может указывать на что угодно, а не только на блок в куче. Что Вы хотите? А то уже пошла толчея воды в ступе
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #67 : Март 16, 2015, 00:30 »

Что-то старожилы совсем опозорились в данном топике. Хоть топикстартер и пишет фигню по большей части, но здесь он затронул больную тему с/с++. Правильный ответ на его вопрос - "потому что си - говно".
Во-первых. delete[] КОНЕЧНО ЖЕ ЗНАЕТ количество элементов. Иначе как он вызовет нужное количество деструкторов?
Во-вторых. Все почему-то зазубрили что массив и указатель - это одно и то же. Но это не так. char * и char [] - это разные типы (в char[] нельзя записать char * но наоборот - можно). К сожалению, в сях работа с массивами не доведена до хоть какого-то ума (к примеру то, что просит топикстартер - передать T[] в ф-ию как пару T* + size)
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #68 : Март 16, 2015, 13:07 »

..совсем опозорились ... пишет фигню ... "потому что си - говно"...в сях работа с массивами не доведена до хоть какого-то ума..
Подобная тональность говорит совсем не о понимании языка, а показывает "чрезмерную начитанность" приведшую к некоторой переоценке своих сил Улыбающийся

Если Вы говорите "указатель", то тем самым уже признаете что никаких гарантий никто не дает. Это просто "адрес" - и все. Интимные подробности delete [] ровным счетом ничего не меняют. Единственное принципиальное решение - избавиться от указателя вообще, а заодно и от new/delete, Именно так и сделано в жабе. Если Вам по душе такой подход - переходите туда. А здесь было и будет так, и по мне это хорошо и правильно: не надо обо мне (навязчиво) заботиться, я сам о себе позабочусь
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #69 : Март 16, 2015, 13:49 »

Подобная тональность говорит совсем не о понимании языка, а показывает "чрезмерную начитанность" приведшую к некоторой переоценке своих сил Улыбающийся

Если Вы говорите "указатель", то тем самым уже признаете что никаких гарантий никто не дает. Это просто "адрес" - и все. Интимные подробности delete [] ровным счетом ничего не меняют. Единственное принципиальное решение - избавиться от указателя вообще, а заодно и от new/delete, Именно так и сделано в жабе. Если Вам по душе такой подход - переходите туда. А здесь было и будет так, и по мне это хорошо и правильно: не надо обо мне (навязчиво) заботиться, я сам о себе позабочусь

Фигню какую-то написали.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #70 : Март 16, 2015, 13:59 »

Данную историческую причину я для себя так и не уяснил. Совершенно ясен факт - new выделяет память и спокойно может знать сколько памяти выделено. Эту информацию ему может вернуть сама ОС (дико звучит, что ОС лучше знает, сколько памяти нужно выделить данной операции, ну пусть так, прогнусь под общественное мнение) или компилятор (если на голом железе). Эту информацию можно "зашить" в выделенный указатель для массивов. Все равно эта информация где-то хранится. Да и вообще! Если уж так, с какого перепугу две версии delete существует, просто и delete[].

Опять же, главный вопрос - почему так не сделали.

Мне кажется, правильные ответы тут звучали, но как-то размазаны по теме Улыбающийся.

delete, конечно же, знает размер выделенной памяти, на которую указывает указатель, возвращаемый new. Ключевое слово "указатель", а не объект какого-то класса/структуры, где можно узнать размер. Почему тогда наравне с этими операторами нет функции, которая бы возвращала размер выделенной памяти для заданного указателя?

Допустим, такая функция есть, пусть её зовут memory_size(), и возвращает она размер памяти по указателю в байтах (хоть в элементах, неважно). Вы можете гарантировать, что в качестве параметра для этой функции будут передаваться только указатели, возвращённые оператором new? А не любой произвольный указатель. И что делать этой функции, если туда передали "левый" указатель? И что ожидать и как обрабатывать ситуации с неверными указателями пользователям этой функции? Ловить исключения? А оно нам надо? Улыбающийся

Например:
Код
C++ (Qt)
void someSortFunc(float *array)
{
   int array_size = memory_size(array);
   ...
}
 
main()
{
   float *a = new float[100];
   float *b = a + 50;
 
   someSortFunc(a);
   someSortFunc(b);
 
   delete[] a;
}
Что произойдёт во время вызова someSortFunc(b)? Какой результат должна вернуть memory_size(b)? Арифметические операции над указателями, надеюсь, никто не отменял.

Таким образом, memory_size() могла бы возвращать размер выделенной памяти, только для указателей, созданных с помощью new. Без всяких сдвигов и т.п. Но таких гарантий никто не может дать. Нужна ли тогда она вообще?

В общем, ответ на вопрос: "Почему нет функции, которая возвращает размер памяти, выделенный new?", Вы получите, когда придумаете реализацию функции memory_size() для произвольного указателя Улыбающийся.
Записан

Пока сам не сделаешь...
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #71 : Март 16, 2015, 15:23 »

Мне кажется, правильные ответы тут звучали, но как-то размазаны по теме Улыбающийся.

delete, конечно же, знает размер выделенной памяти, на которую указывает указатель, возвращаемый new. Ключевое слово "указатель", а не объект какого-то класса/структуры, где можно узнать размер. Почему тогда наравне с этими операторами нет функции, которая бы возвращала размер выделенной памяти для заданного указателя?

Допустим, такая функция есть, пусть её зовут memory_size(), и возвращает она размер памяти по указателю в байтах (хоть в элементах, неважно). Вы можете гарантировать, что в качестве параметра для этой функции будут передаваться только указатели, возвращённые оператором new? А не любой произвольный указатель. И что делать этой функции, если туда передали "левый" указатель? И что ожидать и как обрабатывать ситуации с неверными указателями пользователям этой функции? Ловить исключения? А оно нам надо? Улыбающийся

Например:
Код
C++ (Qt)
void someSortFunc(float *array)
{
   int array_size = memory_size(array);
   ...
}
 
main()
{
   float *a = new float[100];
   float *b = a + 50;
 
   someSortFunc(a);
   someSortFunc(b);
 
   delete[] a;
}
Что произойдёт во время вызова someSortFunc(b)? Какой результат должна вернуть memory_size(b)? Арифметические операции над указателями, надеюсь, никто не отменял.

Таким образом, memory_size() могла бы возвращать размер выделенной памяти, только для указателей, созданных с помощью new. Без всяких сдвигов и т.п. Но таких гарантий никто не может дать. Нужна ли тогда она вообще?

В общем, ответ на вопрос: "Почему нет функции, которая возвращает размер памяти, выделенный new?", Вы получите, когда придумаете реализацию функции memory_size() для произвольного указателя Улыбающийся.
Для сей написанное верно. Понятно, что для УКАЗАТЕЛЯ размер получить нельзя. Но, строго говоря, массив - это НЕ УКАЗАТЕЛЬ. То, что разрабы сей упростили себе жизнь, не отменяет факта, что так сделать нельзя.
В идеальном мире должно было бы так:
Код
C++ (Qt)
void someSortFunc(float array[])
{
   int array_size = memory_size(array);
   ...
}
 
Другое дело, что надо переделывать new (к примеру, возвращать не указатель, а ссылку на T[]) и куча других проблем возникает.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #72 : Март 16, 2015, 15:46 »

В общем, ответ на вопрос: "Почему нет функции, которая возвращает размер памяти, выделенный new?", Вы получите, когда придумаете реализацию функции memory_size() для произвольного указателя Улыбающийся.
Мне не раз приходилось от такой ф-ции избавляться переделывая старый код
Код
C++ (Qt)
void * AllocPtr( size_t size )
{
if (!size) return NULL;
char * ptr = (char *) malloc(size + 16);
if (!ptr) return NULL:
*(size_t *) ptr = size;
return ptr + 16;
}
 
voild FreePtr( void * ptr )
{
if (ptr) free((char *) ptr - 16);
}
 
size_t GetPtrSize( void * ptr)
{
return *(size_t *) ((char *) ptr - 16);
}
 
Улыбающийся
Записан
PinkPanther
Самовар
**
Offline Offline

Сообщений: 169



Просмотр профиля
« Ответ #73 : Март 16, 2015, 18:05 »

Перед тем, как требовать ответ на вопрос, следует разобраться, нужен ли ответ. Размер блока вообще знать не обязательно. Если программисту нужен размер блока, который он же выделяет, речь идет о слабом программисте, ущербном алгоритме и бесполезном приложении, потому что память выделяют под конкретные данные, а не "с запасом". Думаю, со временем функция выделения физической памяти останется у процессора, и доступ к таблице блоков будет ограничен. Выход за границы блока простых данных приведет к ошибке, и в 100% случаев это ошибка алгоритма (программиста).
Записан

Эвтаназия - наше хобби!
AzazelloAV
Гость
« Ответ #74 : Март 16, 2015, 20:13 »

Перед тем, как требовать ответ на вопрос, следует разобраться, нужен ли ответ. Размер блока вообще знать не обязательно. Если программисту нужен размер блока, который он же выделяет, речь идет о слабом программисте, ущербном алгоритме и бесполезном приложении, потому что память выделяют под конкретные данные, а не "с запасом". Думаю, со временем функция выделения физической памяти останется у процессора, и доступ к таблице блоков будет ограничен. Выход за границы блока простых данных приведет к ошибке, и в 100% случаев это ошибка алгоритма (программиста).

Ну уж. Как известно, операция выделения памяти затратная. А вас не интересовало никогда, с практической точки зрения, сколько памяти занимает объект? Например QObject (это всего лишь пример!).  Анализируя с помощью valgrind код, интересные вещи узнаёшь, о которых никогда бы не подумал, что там узкое место. А выделение сотни объектов (тривиальная задача, встречающаяся очень часто) не подлежит анализу на предмет выделения памяти лишь потому, что new/delete  от нас попрятались.

Да и память не плохо выделять с запасом иногда, блоками, что в этом плохого.  Что плохого, что QVector будет выделять память с запасом по 16К (подсознание выплюнуло), чем сотни вызовов выделения памяти.  На низком уровне ОС так и происходит (хотя, данное замечание здесь некорректно).
« Последнее редактирование: Март 16, 2015, 20:17 от AzazelloAV » Записан
Страниц: 1 ... 3 4 [5] 6   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.489 секунд. Запросов: 23.