Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

NULL? Кто он и с чем его едят...

356
16 марта 2003 года
molnij
159 / / 20.06.2000
Скажите пожалуйста умные люди NULL есть в стандарте C++ или нет, и если есть, то какого @#$%^ я должен подключать библиотеки, чтобы компилер его увидел?????? И почему в приведенном коде delete вызывается оба РАЗА!!!!!!!!!!
(заккомментированная строчка при включении не дает никакого эффектА)
#include <stdlib.h>
//#define NULL ((void*)0)

int main(void){
long *a=new long(3);
delete a;
if (a!=NULL)
delete a;
return 1;
}
2.0K
17 марта 2003 года
segev
67 / / 19.01.2003
molnij
Стандарт C++ описывает макрос NULL, он определяется в стандартных заголовочных файлах.
Приведенный пример работает так как должен работать и проблема здесь не в NULL, а в операторе delete, который вовсе не обязан обнулять указатель на освобождаемую память.
356
17 марта 2003 года
molnij
159 / / 20.06.2000
Цитата:
Originally posted by segev
molnij
Стандарт C++ описывает макрос NULL, он определяется в стандартных заголовочных файлах.


Ну это же тупо! почему для работы с каким-нибудь int'ом ничего не нужно подключать, а для NULL'а нужно!!!

Цитата:
Приведенный пример работает так как должен работать и проблема здесь не в NULL, а в операторе delete, который вовсе не обязан обнулять указатель на освобождаемую память.


Мнээээ, тогда глупый вопрос, а как я должен узнать освобождена память или нет????? Ведь при втором вызове delete'а выдается ошибка!

2.0K
17 марта 2003 года
segev
67 / / 19.01.2003
molnij
Цитата:
Ну это же тупо!


Тупо или нет - это вопрос к разработчикам языка, но в любой программе более 3 строчек тебе все ревно придется подключать какие-нибудь заголовки.

Цитата:

как я должен узнать освобождена память или нет??


delete всегда освобождает память, если ей дают правильный указатель.

475
17 марта 2003 года
Winnie
90 / / 20.03.2000
Цитата:

Ну это же тупо! почему для работы с каким-нибудь int'ом ничего не нужно подключать, а для NULL'а нужно!!!



NULL не тип... а значение :) для MAX_INT тоже надо "ашник" подключать


Цитата:

Мнээээ, тогда глупый вопрос, а как я должен узнать освобождена память или нет????? Ведь при втором вызове delete'а выдается ошибка!



обычно делают так:
...
delete a;
a = NULL;
...

иногда для удобства делают макросы
из примеров DX:
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }

426
17 марта 2003 года
Krivonos
112 / / 20.01.2000
int main(void){
long *a=new long(3);
delete a;
if (a!=NULL)
delete a;
return 1;
} [/QUOTE]

Еще одно правило - на один new должен припадать один delete! Аналогично malloc-free.
356
18 марта 2003 года
molnij
159 / / 20.06.2000
Цитата:
segev


Ну насчет трех строчек я бы еще поспорил... ну да ладно...
Тогда еще один вопрос. Чем принципиально отличаются delete a и delete[]a? Только не надо объяснять что второй удаляет всю память а первый нет... Вопрос не в этом, можно ли для int *a=new int; юзать delete []a ???

475
18 марта 2003 года
Winnie
90 / / 20.03.2000
Цитата:
Originally posted by molnij

Ну насчет трех строчек я бы еще поспорил... ну да ладно...
Тогда еще один вопрос. Чем принципиально отличаются delete a и delete[]a? Только не надо объяснять что второй удаляет всю память а первый нет... Вопрос не в этом, можно ли для int *a=new int; юзать delete []a ???



Нельзя
(кстати оба оператора удаляют всю выделенную память)

delete[] a используется для удаления массивов т.е. если проще то в тех случаях когда использовалось:
int *a = new int[10]; // выделяем массив из 10 int

3
18 марта 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by molnij

Ну насчет трех строчек я бы еще поспорил... ну да ладно...
Тогда еще один вопрос. Чем принципиально отличаются delete a и delete[]a? Только не надо объяснять что второй удаляет всю память а первый нет... Вопрос не в этом, можно ли для int *a=new int; юзать delete []a ???



По стандарту языка для new[] соответствует delete[], а для new - delete.
Но современные компиляторы ошибки такого соответствия обходят без постороней помощи.

3
18 марта 2003 года
Green
4.8K / / 20.01.2000
Цитата:
Originally posted by Winnie

int *a = new int[10]; // выделяем массив из 10 int



Не совсем так.

new int[10]; // Создает экземпляр(объект) типа int[10]

Но это уже другая история... :о)

475
18 марта 2003 года
Winnie
90 / / 20.03.2000
Цитата:
Originally posted by Green


Не совсем так.

new int[10]; // Создает экземпляр(объект) типа int[10]

Но это уже другая история... :о)



Даже не знаю стоит ли углубляться в филососфские различия массива из 10 элементов int и экземпляра объекта типа int[10].....

по моему массив все-таки проще для понимания.. а экземпляры пусть у классов будут...

2.0K
20 марта 2003 года
segev
67 / / 19.01.2003
molnij
Цитата:

Тогда еще один вопрос. Чем принципиально отличаются delete a и delete[]a? Только не надо объяснять что второй удаляет всю память а первый нет... Вопрос не в этом, можно ли для int *a=new int; юзать delete []a ???


Ответ зависит от, того какой компилятор ты используешь.
Не поленился, проверил компиляторы от MS и Borland на примере с int'ми. Получились следующие результаты:
В MS VC 6 операторы delete и delete[] транслируются в вызов одной и той же внутренней функции т.е. с позиции пользователя они совершенно одинаковы.
В Borland C++ 5.5 оператор delete реализуется через delete[], здесь тоже получается никакой разницы, можно даже попробовать "оптимизировать" программу: вместо delete[] писать delete, получиться на пару машинных команд меньше :).
Если же ты хочешь присать переносимые программы - придерживайся стандарта. Насколько я понимаю, введением двух операторов delete разработчики стандарта хотели облегчить жизнь создателям компиляторов, но те сказали, что сами с усами,
и обошлись по сути дела одним.
Про 3 строчки, вообще-то я образно выразился: глупо писать программу без заголовков.
Green

Цитата:

new int[10]; // Создает экземпляр(объект) типа int[10]


Оригинально. Это что-то из разряда Think different ?

475
20 марта 2003 года
Winnie
90 / / 20.03.2000
Цитата:
Originally posted by segev
molnij
В MS VC 6 операторы delete и delete[] транслируются в вызов одной и той же внутренней функции т.е. с позиции пользователя они совершенно одинаковы.
В Borland C++ 5.5 оператор delete реализуется через delete[], здесь тоже получается никакой разницы, можно даже попробовать "оптимизировать" программу: вместо delete[] писать delete, получиться на пару машинных команд меньше :).



не советовал бы таким образом оптимизировать...
Все это хорошо только для простых типов и классов у которых нет деструктора (деструктор по умолчанию)...

попробуйте выполнить код:

Код:
class CTest
{
public:
    ~CTest() {}
};

int main(int argc, char* argv[])
{
    CTest *array = new CTest[10];
    delete array;
    return 0;
}


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

Так что рекомендую во всех случаях следовать соответсвию new - delete, new[] - delete[] :)

P.S. кстати если в примере закоментировать деструктор то программа перестает падать :)

P.P.S. проверял на VC6.0 и eVC3.0
1.9K
20 марта 2003 года
kswapd
93 / / 08.02.2003
А зачем вобще нужен этот NULL? Поему просто 0 понятней и красивей. Да и Страуструп рекомендует 0 использовать.
475
20 марта 2003 года
Winnie
90 / / 20.03.2000
Цитата:
Originally posted by kswapd
А зачем вобще нужен этот NULL? Поему просто 0 понятней и красивей. Да и Страуструп рекомендует 0 использовать.



хм..... традиция-с....
в принципе одно и тоже хотя на некоторых платформах NULL наверно и не 0 может быть...

2.0K
21 марта 2003 года
segev
67 / / 19.01.2003
Winnie
По сложным типам данных согласен 100%, тут все намного сложней.
Я писал только про int.
475
21 марта 2003 года
Winnie
90 / / 20.03.2000
Цитата:
Originally posted by segev
Winnie
По сложным типам данных согласен 100%, тут все намного сложней.
Я писал только про int.



ну да... вобщем такая оптимизация и разряда "dirty trick" т.е. если сильно надо и сильно уверен то можно... но сильно не рекомендуется.. особенно начинающим

356
21 марта 2003 года
molnij
159 / / 20.06.2000
Цитата:
Originally posted by kswapd
А зачем вобще нужен этот NULL? Поему просто 0 понятней и красивей. Да и Страуструп рекомендует 0 использовать.


NULL нужен для того, чтобы не писать (void *)(0)...А просто ноль вообще-то юзать вроде бы нельзя...

А *a=new int; и a=new int[1] как нибудь различаются??

1.9K
21 марта 2003 года
kswapd
93 / / 08.02.2003
Цитата:
Originally posted by molnij

NULL нужен для того, чтобы не писать (void *)(0)...А просто ноль вообще-то юзать вроде бы нельзя...



Можно. Он автоматически преобразуется в void*. И вобще что такое 0? Какого он типа? int, char, void*? 0 разные бывают :) У каждого типа свой :)

2.0K
23 марта 2003 года
segev
67 / / 19.01.2003
kswapd
Цитата:

А зачем вобще нужен этот NULL? Поему просто 0 понятней и красивей. Да и Страуструп рекомендует 0 использовать.


0 может быть и красивее, но не понятней. Особенно когда разбираешься в чужой программе: если видишь
if (somevar == NULL) {...}
сразу ясно, somevar - это указатель, а не int и не char, как можно подумать глядя на
if (somevar == 0) {...}
Да и существование архитектур, где NULL вовсе не ноль тоже не исключено (хотя я таких не знаю).
И еще, подскажи, где Страуструп рекомендует использовать 0. В 3-ем издании Языка C++ что-то я такого не припомню (возможно ошибаюсь).

Winnie

Цитата:

вобщем такая оптимизация и разряда "dirty trick"


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

1.9K
23 марта 2003 года
kswapd
93 / / 08.02.2003
Цитата:
Originally posted by segev


0 может быть и красивее, но не понятней. Особенно когда разбираешься в чужой программе: если видишь
if (somevar == NULL) {...}
сразу ясно, somevar - это указатель, а не int и не char, как можно подумать глядя на
if (somevar == 0) {...}
Да и существование архитектур, где NULL вовсе не ноль тоже не исключено (хотя я таких не знаю).
И еще, подскажи, где Страуструп рекомендует использовать 0. В 3-ем издании Языка C++ что-то я такого не припомню (возможно ошибаюсь).



Иммено в этой книге. К сожалению сейчас ее под рукой нет, страницы не назову. Но где-то в начале, где он объяняет почему в 90% случаев не надо использовать препроцессор :) А про somevar лучше вобще if(!somevar) {...}

475
24 марта 2003 года
Winnie
90 / / 20.03.2000
Цитата:
Originally posted by kswapd


Иммено в этой книге. К сожалению сейчас ее под рукой нет, страницы не назову. Но где-то в начале, где он объяняет почему в 90% случаев не надо использовать препроцессор :) А про somevar лучше вобще if(!somevar) {...}



Страуструп. Издание 3-е.
5.1.1. Ноль (стр 128)

Ноль (0) имеет тип int. Благодаря стандартным преобразованиям, 0 можно испоьзовать в качестве констаныт любого интегрального типа, типа с плавающей точкой, указателя или указателя на член класса. ип нуля определяется по контексту. Ноль как правило (но не всегда), будет физически представлен в виде последовательности нулевых битов соответсвующей длины.
Гарантируется, что нет объектов с нулевым адресом. Следовательно, указатель, равный нулю, можно интерпретировать как указатель, который не на что не ссылается.
В языке C очень популярно определять макрос NULL для представления такого нулевого указателя. Так как в C++ типы проверяются более жестко, использование банального нуля вместо NULL приведет к меньшим проблемам. Если вы чуствуете, что просто обязаны определить NULL, воспользуйтесь
const int NULL = 0;

От себя: я предпочитаю все-таки использовать NULL (во-первых традиция-с... во-вторых еще много приходится писать на C а не на C++)

2.0K
26 марта 2003 года
segev
67 / / 19.01.2003
Winnie
kswapd

Спасибо за подсказку.

P.S. Я тоже за NULL, хотя практически все делаю на C++. Попривычнее как-то.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог