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

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

Страниц: [1] 2 3 ... 6   Вниз
  Печать  
Автор Тема: Плюсолюбителям  (Прочитано 42971 раз)
AzazelloAV
Гость
« : Март 09, 2015, 00:27 »

Qt ни причём, однако.
Являюсь "пользователем" библиотеки, поэтому напишу.

Объясните гуру плюсов (и просто С) вещь, которая меня уже давно "мучает".
Зачем, зачем при передаче массива (к примеру char*, не строки) в API (любой) передаётся его размер?

Я точно уверен, что объяснения этому есть, но грамотный запрос в поисковики так и не смог составить, чтобы получить ответ.

Приведу пример условного кода.

char * c = new 100;
void somFunct(c,100)
delete []с;

Этот когд всегда мне мозг выносит.


Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #1 : Март 09, 2015, 00:35 »

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

Используйте в плюсах класс vector -- тот же массив, но более продвинутый Улыбающийся
Записан

AzazelloAV
Гость
« Ответ #2 : Март 09, 2015, 00:48 »

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

Используйте в плюсах класс vector -- тот же массив, но более продвинутый Улыбающийся

Вы меня не поняли. Qt  здесь вообще далеко.
Я привел пседокод, процитирую его:

char * c = new 100;
void somFunct(c,100)
delete []с;

Cмущает, что нет delete[100]c

Другими словами delete знает, сколько ему данных удалять, а в других случаях: "Извените, размер массива не известен"
« Последнее редактирование: Март 09, 2015, 00:59 от AzazelloAV » Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #3 : Март 09, 2015, 01:13 »

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

Используйте в плюсах класс vector -- тот же массив, но более продвинутый Улыбающийся

Вы меня не поняли. Qt  здесь вообще далеко.

это вы меня не поняли )
я говорил про vector, или std::vector, а не про QVector Улыбающийся
vector это стандартный класс плюсов

А вот откуда delete знает сколько ему удалять я не знаю, подождем ответа более опытных форумчан Подмигивающий
Записан

Bepec
Гость
« Ответ #4 : Март 09, 2015, 01:13 »

Выделить можно 100, а использовать 20. Оставшиеся 80 будут забиты мусором.
Передаем мы собственно контейнер и размер используемого пространства.

[Псевдокод]
Допустим мы инициализируем массив из 30 элементов.
Код:
char *c = new 30;
c = "poiuyhjuyhjuytghytrfgtredgbhyj"
 и добавляем в него слово Привет.
Код:
strcpy(c,"Привет");
c = "Привет\0uyhjuytghytrfgtredgbhyj"
И нам надо вывести слово на экран.
Код:
PrintStr(c, 6);
На экране - "Привет"

Если просто передать массив с его размером, то получим следующее
Код:
PrintStr(c, 30);
На экране - "Привет\0uyhjuytghytrfgtredgbhyj"

Записан
Swa
Самовар
**
Offline Offline

Сообщений: 170


Просмотр профиля
« Ответ #5 : Март 09, 2015, 01:30 »

Другими словами delete знает, сколько ему данных удалять, а в других случаях: "Извените, размер массива не известен"
Да, именно так.
Вот тут немного написано.
Записан
AzazelloAV
Гость
« Ответ #6 : Март 09, 2015, 01:44 »

Выделить можно 100, а использовать 20. Оставшиеся 80 будут забиты мусором.
Передаем мы собственно контейнер и размер используемого пространства.

Допустим мы инициализируем массив из 30 элементов.


Не не не не.
С твоей стороны используется софизм, который в тупик заведёт.
Во первых, нужно забыть про строки (они же с 0), а во вторых, определить правила.

1. Как есть, так есть. Цель просто понять, почему по историческим причинам так.
2. Размер передается для избежания переполнения, безопасности и т.д.
3. delete  знает размер данных и спокойно их удаляет. Если пункт 2 не подходит (нужно хитрый размер по другим причинам) - я не видел таких функций. Тогда все остальные должны быть с одним параметром.

Даже если есть такие функции, в которых размер передается для "хитрых" вещей -  я их не встречал, по крайней мере в ВинАПИ (с линухом АЙПИ напрямую не работал)

Если нужен максимальный размер, вы видели такие функции, которые не передавали бы размер?
« Последнее редактирование: Март 09, 2015, 02:07 от AzazelloAV » Записан
AzazelloAV
Гость
« Ответ #7 : Март 09, 2015, 01:46 »

Другими словами delete знает, сколько ему данных удалять, а в других случаях: "Извените, размер массива не известен"
Да, именно так.
Вот тут немного написано.

Та там тоска читать, мы же не компиляторы пишем, объясните в двух словах, с какого.

Ага, ну это не ответ на вопрос. Страуструп внятно в своих книгах описывает даже где хранятся эти самые байты (размер массива).

Вопрос же почему там так, а там - мы не знаем.
« Последнее редактирование: Март 09, 2015, 02:02 от AzazelloAV » Записан
Bepec
Гость
« Ответ #8 : Март 09, 2015, 01:47 »

Собственно передача размера даёт вам гибкость и возможность реализовать функцию как угодно, не меняя её входных аргументов.
Функция на 1 символ и миллион будет иметь один прототип. Простор для вашей фантазии.
Записан
AzazelloAV
Гость
« Ответ #9 : Март 09, 2015, 01:53 »

Собственно передача размера даёт вам гибкость и возможность реализовать функцию как угодно, не меняя её входных аргументов.
Функция на 1 символ и миллион будет иметь один прототип. Простор для вашей фантазии.


Повторюсь - это не так. Передается "не для фантазии", а для "размера". Какая гибкость может быть в вызове функции "получить полный путь к файлу"?  Если я не ошибаюсь, в примерах МСДН был полный путь [1024] (буфер), какую гибкость можно получить уменьшая или увеличивая этот размер?
« Последнее редактирование: Март 09, 2015, 02:17 от AzazelloAV » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Собственно передача размера даёт вам гибкость и возможность реализовать функцию как угодно, не меняя её входных аргументов.
Как ни странно, это "правельный ответ"

Другими словами delete знает, сколько ему данных удалять, а в других случаях: "Извените, размер массива не известен"
delete знает размер выделенного блока, который совсем не 100. Однако
Код
C++ (Qt)
void SomeFunc(  char * c )
{
...
}
SomeFunc ничего не знает о размере строки. "c" может быть чем угодно, напр подстрокой в др строке. глобальной переменной, буфером др класса и.т.д. Если размер не передан явно, то SomeFunc остается полагать что строка заканчивается нулем.

Др. словами не надо обобщать частный случай "строка в куче" - даже в этом случае точное число символов неизвестно
Записан
RSATom
Гость
« Ответ #11 : Март 09, 2015, 10:02 »

Например потому что выделенную память можно использовать вот так:

Код
C++ (Qt)
char* c = new char[100];
somFunc(c, 10);
somFunc(c+10, 10);
somFunc(c+20, 80);
delete [] с;
 

а указывать в delete [] размер выделенной памяти не нужно просто потому что CRT знает сколько памяти было выделено.
« Последнее редактирование: Март 09, 2015, 10:03 от RSATom » Записан
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #12 : Март 09, 2015, 11:37 »

Cмущает, что нет delete[100]c
Другими словами delete знает, сколько ему данных удалять, а в других случаях: "Извените, размер массива не известен"
operator delete() и operator delete[]() - это разные операторы и предназначены для освобождения памяти, выделенной с помощью разных операторов operator new() и operator new[]() соответственно. Собственно, это все объясняет - требования языка.
Если бы вы посмотрели материал, который вам предложил Swa, вы бы поняли, что использование delete для массива может привести не только к неполному освобождению памяти, но и к краху программы. И связано это с тем, что в разных реализациях компиляторов new и new[] по-разному выделяют память и хранят ее размер.
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
AzazelloAV
Гость
« Ответ #13 : Март 09, 2015, 15:35 »

Например потому что выделенную память можно использовать вот так:

Код
C++ (Qt)
char* c = new char[100];
somFunc(c, 10);
somFunc(c+10, 10);
somFunc(c+20, 80);
delete [] с;
 

а указывать в delete [] размер выделенной памяти не нужно просто потому что CRT знает сколько памяти было выделено.

Это хороший пример, и действительно....
Но мы его разобъём об скалы уязвимости, которыми пестрят книги....

Код
C++ (Qt)
somFunc(c+20, 100);
 

Я всего лишь говорю, что везде классика предлагает: "нужно передавать размер, потому как его никто не знает".
Нигде я не встречал оправданий, что размер передаётся для  вашего варианта передачи.
Записан
AzazelloAV
Гость
« Ответ #14 : Март 09, 2015, 15:44 »

Цитировать
operator delete() и operator delete[]() - это разные операторы и предназначены для освобождения памяти, выделенной с помощью разных операторов operator new() и operator new[]() соответственно. Собственно, это все объясняет - требования языка.
Если бы вы посмотрели материал, который вам предложил Swa, вы бы поняли, что использование delete для массива может привести не только к неполному освобождению памяти, но и к краху программы. И связано это с тем, что в разных реализациях компиляторов new и new[] по-разному выделяют память и хранят ее размер.
То, что delete может хранится по разному для разных компиляторах ничего не значит. Также может разными компиляторами реализовывать VMT. Но т.к. это происходит в одном "пространстве компилятора", это не важно, он же знает где хранится.
Хотя в общем случае это не так, все хранят одинаково, иначе были бы сложности в вызове функций delete для разных библиотек.
Ведь есть функции, которые возращают новый объект, выделеный, вы им передаете только указатель, освобождение ложится на вас. Если, то, что вы говорите было правдой, мы бы не смогли пользоваться такой библиотекой с другим компилятором.
Записан
Страниц: [1] 2 3 ... 6   Вверх
  Печать  
 
Перейти в:  


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