Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.09.2010, 09:09   #1
Ivan_32
somewhere else
Участник клуба
 
Аватар для Ivan_32
 
Регистрация: 17.07.2008
Сообщений: 1,409
По умолчанию Способы создания объектов и арифметика указателей

Вот сам код:
http://paste.org.ru/?fna8v4

Проблема следующая:
Я страх как не хочу видеть в коде ссылочные типы на объект и уж тем более очень не хочется видеть выражения вида (*a)[0]. Опять же не очень хочется делать некий абстрактный класс для сокрытия арифметики указателей( да и можно ли такое сделать в данном случае? ), да и не знаю как.
Как можно данную проблему решить и что не так у меня в классах, может быть я где то допустил ошибку?

Так же интересует чем различаются данные способы создания объектов:
List* a=new List(0);
List b(0);
Я так понимаю первый живет ровно до тех пор пока на него ссылается хотя бы один указатель, а вот второй это просто напросто ссылка на объект? Первый не умрет если на него будет что либо ссылается, а вот второй умрет сразу после выхода из области видимости?

PS: Меня так же посещала мысль сделать из этого класса функтор, это конечно решит проблему но выглядит как то уж криво слишком, с таким же успехом можно будет и обычную функцию использовать. Хочется настоящей неподдельной инкапсуляции, так что б тип данным выглядел взаправдашним
"Тяжело в учении, легко в бою" - А.В. Суворов
Ivan_32 вне форума Ответить с цитированием
Старый 11.09.2010, 10:01   #2
Гром
Старожил
 
Аватар для Гром
 
Регистрация: 21.03.2009
Сообщений: 2,193
По умолчанию

А зачем вам вообще там понадобились ссылки?
Кстати, разыменовывать ссылки вообще не надо.
Код:
std::string s = "Hello";
std::string& ss = s;
ss += ", world!";
std::cout << s;
Выведет "Hello, world!"
Разыменовывать нужно только указатели. Вообще почитайте про ссылки побольше.
По поводу
Код:
List* a=new List(0);
List b(0);
В первом случае память под объект выделяется динамически, во втором - статически. Соответственно, второй объект автоматически уничтожается как только его имя выйдет из зоны видимости, а первый - только тогда, когда он будет явно удален при помощи оператора delete.
А насчет
Цитата:
пока на него ссылается хотя бы один указатель
- это вы, батенька, сборщиком мусора испорчены.
В стандартном C++ сборщика мусора нет, и вам необходимо явно удалять все динамически создаваемые объекты, иначе у вас будут утечки памяти.
Код:
void f()
{
int* a = new int;
*a = 10;
}
Объявляем это мы указатель (кстати, указатель тоже является переменной, а стало быть, и под него выделяется память), выделяем область памяти под число, присваиваем указателю адрес этой области памяти. А потом при выходе из функции статически объявленный указатель взял и уничтожился, а объект, на который он указывал, остался и повис в памяти мертвым грузом. Адрес его никому уже не известен, а память не освобождена.
Простые и красивые программы - коды программ + учебник C++
Создание игры - взгляд изнутри - сайт проекта
Тема на форуме, посвященная ему же
Гром вне форума Ответить с цитированием
Старый 11.09.2010, 10:05   #3
Ivan_32
somewhere else
Участник клуба
 
Аватар для Ivan_32
 
Регистрация: 17.07.2008
Сообщений: 1,409
По умолчанию

Ссылка это первое что пришло в голову в качестве способа избавится от конструкций вида (*a)[0]. С выделением памяти понятно, спасибо, а вот как избавится от этой уродливой конструкции? (*a)[0]. Должен же быть способ?
"Тяжело в учении, легко в бою" - А.В. Суворов
Ivan_32 вне форума Ответить с цитированием
Старый 11.09.2010, 10:11   #4
the_deer_one
Участник клуба
 
Аватар для the_deer_one
 
Регистрация: 04.04.2010
Сообщений: 1,554
По умолчанию

Ivan_32
(стёрто)
(тьфу, пока отвечал, вы уже пять постов написали, экие вы быстрые)

Цитата:
Как можно данную проблему решить
Почему проблема? Нормальный синтаксис с++. Это хорошо, что можно явно эти вещи указывать.
the_deer_one вне форума Ответить с цитированием
Старый 11.09.2010, 10:23   #5
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Цитата:
Сообщение от Ivan_32 Посмотреть сообщение
Я страх как не хочу видеть в коде ссылочные типы на объект и уж тем более очень не хочется видеть выражения вида (*a)[0]. Опять же не очень хочется делать некий абстрактный класс для сокрытия арифметики указателей( да и можно ли такое сделать в данном случае? ), да и не знаю как.
Значит С++ не подходит. Пишите на делфи, шарпе, яве или еще на чем.
Цитата:
Сообщение от Ivan_32 Посмотреть сообщение
Как можно данную проблему решить и что не так у меня в классах, может быть я где то допустил ошибку?
Класс List глуп до безобразия. Это объекдинение недостатков массивов и списков вместе взятые.
Посмотрим на плюсы и минусы двусвязных списков:
+ Простой и относительно быстрый перебор элементов как слева-направо, так и справа-налево
+ Быстрая вставка элементов (в том числе и в центр списка)
- Медленный доступ по индексу
- Избыточность памяти (на каждый элемент лишние 2 указателя на соседние элементы)
Класс List позволяет вставить элемент только в конец списка, причем делает это ужасно неоптимально и медленно (почему бы не хранить указатель на последний элемент списка рядом с ListNode *first?
Получить элемент можно только по индексу, а это тоже ужасно медленно для списка.
Нужно перебрать все элементы - пиши цикл for и к каждому элементу достукивайся по индексу. И для каждого элемента список будет проверяться с первого элемента.
ListNode в данном виде обязан быть struct, а не class. Никакой инкапсуляции. Я легко могу получить указатель на следующий/предыдущий элемент списка и поломать весь список. Эти недостатки убираются тем, что пользователь оперируется только классом List, а ListNode в явном виде не используется. Только вот как будет в этом случае реализована нормальная вставка в центр списка, перебор всех элементов,... я не представляю.
Цитата:
Сообщение от Ivan_32 Посмотреть сообщение
Так же интересует чем различаются данные способы создания объектов:
List* a=new List(0);
List b(0);
Я так понимаю первый живет ровно до тех пор пока на него ссылается хотя бы один указатель, а вот второй это просто напросто ссылка на объект? Первый не умрет если на него будет что либо ссылается, а вот второй умрет сразу после выхода из области видимости?
Нет. Не так всё.
Первый случай с new - создание объекта в куче. Объект будет жить до тех пор, пока не вызовется delete для него. Не удалили объект, потеряли на него указатель - получили утечку памяти, т.к. объект уже никто не уничтожит.
Во втором случае объект создаётся на стеке. Его удалять вручную нельзя, а память очистится автоматически, как только закончится область видимости объекта. Объект - локальная переменная функции, значит удалится при завершении работы функции. Объект - член класса, значит удалится при выполнении деструктора.
Объекты, созданные на стеке, можно считать безопасными в плане утечек памяти. При создании объекта в куче, нужно следить за исключениями, не забывать их удалять,... Это всё нужно продумывать при проектировании программы, библиотеки,... Общий стиль управления памятью должен быть. Лучше всего придерживаться правила: кто создал объект, тот его и должен удалить.
Так же есть так называемые "умные" указатели (auto_ptr, shared_ptr,...) именно при их использовании, объекты будут жить до тех пор, пока они кому-то нужны. Ну это одна из стратегий, а их для "умных" указателей несколько
Цитата:
Сообщение от Ivan_32 Посмотреть сообщение
PS: Меня так же посещала мысль сделать из этого класса функтор, это конечно решит проблему но выглядит как то уж криво слишком, с таким же успехом можно будет и обычную функцию использовать. Хочется настоящей неподдельной инкапсуляции, так что б тип данным выглядел взаправдашним
Посмотрите на библиотеку STL и в частности класс sdt::list. Именно такие контейнеры считаются тру С++. Хотя код у них ужасен и непонятен
pu4koff вне форума Ответить с цитированием
Старый 11.09.2010, 16:46   #6
f.hump
C/C++, Asm
Участник клуба
 
Аватар для f.hump
 
Регистрация: 02.03.2010
Сообщений: 1,323
По умолчанию

Цитата:
качестве способа избавится от конструкций вида (*a)[0]
на самом деле если а указатель на некоторый объект, то не совсем понятно зачем делать действительно мрачноватое построение, как в цитате. Полезно помнить, что укзатель и массив это синонимы в с/с++, и что есть два интересных оператора '.' (reference to reference) и '->' (pointer to reference), поэтому будут справедливы выражения типа
Код:
a[0].ObjectMethod(..)
(*a).ObjectMethod(..)
a->ObjectMethod(..)

a[0].ObjectProperty
(*a).ObjectProperty
a->ObjectProperty
f.hump вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Понятия принципа создания динамических объектов Golovastik Общие вопросы C/C++ 25 05.06.2010 21:18
способы ввода массива Алексей Долгов Помощь студентам 0 24.05.2010 19:51
проблема создания массива объектов Meduzza Общие вопросы C/C++ 3 28.05.2009 05:07
способы работы с Б.Д. Ванька БД в Delphi 1 20.11.2007 22:12
способы создания баз Ванька БД в Delphi 2 20.11.2007 12:42