Это баг или фича?? (Удаление динамического массива)

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

Ответить
korisk
Сообщения: 14
Зарегистрирован: 10 ноя 2008, 22:03
Откуда: Sarov
Контактная информация:

12 ноя 2008, 20:02

/*Wed, 12 Nov 2008 19:27:55 +0300*/
#include <iostream>
using namespace std;

class B{
public:
B(){
cout << "start" << endl;
}
~B(){
cout << "end" << endl;
}
};


void d(B *b){
b = new B[3];
}


int main()
{
B* bb;
d(bb);
// bb = new B[3];
delete[] bb;
return 0;
}

после выполнения кода, скомпилированого gcc
программав выводит 3 слова start и 720914 end.

Это баг или фича?
Albor
Сообщения: 482
Зарегистрирован: 06 сен 2004, 13:34
Откуда: Днепропетровск

13 ноя 2008, 07:20

А почему в жалобную книгу? Жалуетесь на компилятор? Ограничивает, сволочь, фантазию :) ? Передача параметров по ссылке и по значению. Приведенный код выдаёт Warning о том, что указатель bb не инициализируется. От сюда и проблема. Прототип ф-ции должен быть либо B * d(), либо void d(B*&b).
korisk
Сообщения: 14
Зарегистрирован: 10 ноя 2008, 22:03
Откуда: Sarov
Контактная информация:

13 ноя 2008, 22:04

О! Я кажеться понял, указатель на динамический массив это не просто указатель, там видимо есть ещё какие-то добавки, поэтому приходится использовать ссылки. Хотя не понятно почему при выполнении оператора =() B*d() преобразование правильное, а d(B*) не пверное.

И почему всегда 720914 :)
Компилятор gcc (GCC) 4.1.2

А в эту ветку написал, потому что недавно на этом форуме, :) а правила тут хитрые, сразу не понял где писать можно.

В общем, спасибо.

Удач.
Albor
Сообщения: 482
Зарегистрирован: 06 сен 2004, 13:34
Откуда: Днепропетровск

14 ноя 2008, 06:42

При чём здесь преобразование? При передаче параметра по значению, функция работает с копией переданной переменной, которая, по завершению работы функции, уничтожается, а оригинал остаётся без изменений. Присвой указателю bb, какое либо значение, например 0, поставь точку останова на строку, освобождающую память и запусти дебаггер. Ты увидишь, что значение указателя не изменилось. Если использовать прототип B* d(); - это значит, что ф-ция возвращает указатель на B, а bb=функция, сохраняет возвращённое значение в переменной bb. А если передать параметр по ссылке, то функция будет работать с оригиналом переменной, который, при выходе, не уничтожается. Надеюсь объяснил понятно.
korisk
Сообщения: 14
Зарегистрирован: 10 ноя 2008, 22:03
Откуда: Sarov
Контактная информация:

14 ноя 2008, 20:36

Да, спасибо большое за доходчивое объяснение :)
До меня наконец-то дошло.
Аватара пользователя
Airhand
Сообщения: 234
Зарегистрирован: 06 окт 2005, 16:21
Откуда: Dnepropetrovsk

24 ноя 2008, 13:00

Ты удаляеш указатель как массив. А количество элементов оно хранит перед первым элементом массива (так реализовано). Поэтому вызывается деструктор столько раз. Сделай delete B и ты увидиш разницу.
korisk
Сообщения: 14
Зарегистрирован: 10 ноя 2008, 22:03
Откуда: Sarov
Контактная информация:

24 ноя 2008, 20:10

Спасибо, буду знать )
atavin-ta
Сообщения: 572
Зарегистрирован: 30 янв 2009, 06:38

09 фев 2009, 09:23

&quot писал(а):О! Я кажеться понял, указатель на динамический массив это не просто указатель, там видимо есть ещё какие-то добавки, поэтому приходится использовать ссылки. Хотя не понятно почему при выполнении оператора =() B*d() преобразование правильное, а d(B*) не пверное.
Указатель на массив - это простой укзатаель. Но тебе надо передать его в функцию из этой же функции получить его назад. С этим и связана необходимость передавать не указатель а ссылку на него. Фактически передаётся указатель на указатель. Но ссылка - это указатель специального вида, с которым применяется синтаксис самой величины. В результате ты передаёшь указатель на указатель, а работаешь с ним как с тем простым указателем, на который он указывает.
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
BBB
Сообщения: 1272
Зарегистрирован: 27 дек 2005, 13:37

09 фев 2009, 09:33

Albor писал(а):Прототип ф-ции должен быть либо B * d(), либо void d(B*&b).
Ну, есть еще вариант в "исконном C-шном стиле", в синтаксите которого не было, насколько я знаю передачи параметров по ссылке:

void d(B**b);

и вызов:

B* bb;
d(&bb);
Ответить