Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Ссылки и указатели. Что удобнее возвращать из метода?  (Прочитано 25820 раз)
0 Пользователей и 9 Гостей смотрят эту тему.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« : 11-12-2010 22:33 » 

Пример:

Код: (C++)
class A
{
public:
  int x;
  int y;
  A(int x, int y) : x(x), y(y) { };
};

typedef std::map<int, A*> ACollection;

class B
{
  ACollection list;
public:
  const A & a(int index) const;
  const A * a(int index) const;
};

const A & B::a(int index) const
{
  return *(list[index]);
}

const A * B::a(int index) const
{
  return list[index];
}

Какие тут достоинства и недостатки у методов B::a?

Код: (C++)
// B b;

var = b.a(1).x;
var += b.a(1).y;

ptr = b.a(1);
var = ptr->x;
var += ptr->y;

С одной стороны, работа с ссылкой как-то проще. С другой, поиск в map для каждого доступа будет накладен.

И с одной переменной (как с указателем) не поработаешь (даже если убрать const):

Код: (C++)
A &ref = b.a(1);
ref = b.a(2); // присвоение b.a(1) = b.a(2)

А указатель можно засунуть в delete...
Или все же можно от такого предохраниться?
« Последнее редактирование: 13-12-2010 04:31 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 11-12-2010 22:39 » 

При получении извне, указатель всегда нужно проверять на NULL.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 12-12-2010 08:47 » 

а по мне, так между ссылками и указателями нет разницы. Всё, что делается с одним, можно сделать и с другим
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 12-12-2010 09:43 » 

Леш, ты несколько заблуждаешься. Ссылка намного более капризна.

Недостатки ссылок:
1. Нельзя объявить ссылку заранее - она требует инициализации при создании.
2. Нельзя изменить ссылку, чтобы она ссылалась на другой объект.
3. Случайное присвоение ссылке может испортить объект, на который она ссылается (если объект не const).

Недостатки указателей:
1. Требует разыменования (*) или более длинной записи (->).
2. Чередования указателей, объектов и ссылок могут запутать (a->b().c.d->e()->f = 1;).
3. Указатель можно ненароком удалить (передать в delete), даже если это не требуется.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 12-12-2010 13:56 » 

Ссылки оказались удобны для хранения внутри объекта динамических объектов, передаваемых в параметрах конструктору и уничтожаемых одновременно с объектом-носителем: нет нужды вызывать delete (не запутаешься) и гарантированная инициализация, а также нельзя передать в конструктор NULL-указатель (гарантированный Segmentation fault).

Код: (Text) с++
#include <stdio.h>

class TestData
{
public:
    int x;

    TestData() { puts("_ create TestData"); };
    ~TestData() { puts("_ destroy TestData"); };
};

class Test
{
    TestData &data;
public:
    Test(TestData &initData) : data(initData) { puts("_ create Test"); };
    ~Test() { puts("_ destroy Test"); };
    int x() { return data.x; };
};

int main(void)
{
    TestData *td = new TestData();
    Test *t;

    td->x = 10;
    t = new Test(*td);

    printf("Test: %d\n", t->x());

    delete t;
    return 0;
}

_ create TestData
_ create Test
Test: 10
_ destroy Test
_ destroy TestData



Добавлено через 59 минут и 59 секунд:
Ошибочка вышла... Фига с два он вызывает деструктор Жаль
Т.е. для ссылок деструктор не вызывается. Жаль. Разве что добавить в ~Test код: delete &data;
« Последнее редактирование: 12-12-2010 15:02 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 12-12-2010 19:08 » 

Леш, ты несколько заблуждаешься. Ссылка намного более капризна.

Недостатки ссылок:
Недостатки указателей:
это не недостатки, а следствие их смысла (который поддерживается компилятором): указатель - хранилище адреса, а ссылка - синоним (но внутри - такое же хранилище адреса).

Цитата
Ошибочка вышла... Фига с два он вызывает деструктор
Т.е. для ссылок деструктор не вызывается. Жаль. Разве что добавить в ~Test код: delete &data;

это потому, что я не заблуждаюсь Улыбаюсь
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 12-12-2010 20:19 » 

Это я пытаюсь внедрить модели в насквозь запроцедуренный код — его стало мучительно поддерживать и изменять. Приходится заново изучать давно забытое Улыбаюсь
« Последнее редактирование: 12-12-2010 20:21 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #7 : 13-12-2010 04:20 » 

С одной стороны, работа с ссылкой как-то проще. С другой, поиск в map для каждого доступа будет накладен.

И с одной переменной (как с указателем) не поработаешь (даже если убрать const):

Код: (C++)
A &ref = b.a(1);
ref = b.a(2); // присвоение b.a(1) = b.a(2)

не понял тебя, ни про map, не про присвоить
про недостатки ссылок не согласен, это своиства, дающие некоторые бонусы
у Брюса Эллеля насколько я помню хорошо про это расписано и у Скотта Мейерса

указатели на внетренние данные стараюсь не возвращать, за исключением случаев, когда указатель более уместен
народ рекомендует не использовать ссылки при передаче параметров, если внутри меняется значение хранимое по ссылке, т.к. это делает не очевидным поведение функции
http://easy-coding.blogspot.com/2010/11/blog-post.html

ну это такой вопрос для холивара я бы сказал, что круче, то или это
лично я просто стараюсь выбирать их так, что бы поведение функций было очевидно
Записан

Странно всё это....
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 13-12-2010 04:30 » 

Антон, чего не понятного "про map"? Не цитировать де пример в полном объеме Ага

Код: (C++)
const A & B::a(int index) const
{
  return *(list[index]);
}

const A * B::a(int index) const
{
  return list[index];
}

Код: (C++)
var = b.a(1).x;
var += b.a(1).y;

Я про это. Чтобы, используя вариант с возвращаемой ссылкой, доступиться к N свойствам требуется вызвать код N раз.
Или делать локальную ссылку:

Код: (C++)
{
  A &ref = b.a(1);
  var = ref.x;
  var += ref.y;
}

В примере была опечатка - убрал одну звездочку.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #9 : 13-12-2010 04:55 » 

1. тебе и с указателем и без нужно вызывать поиск N раз, для контейнеров не хранящих данные одним блоков в памяти, нельзя применять алгебру указателей
2. ах вот ты о чём, перечитал первый пост и твоё дополнение и наконец догнал Улыбаюсь

в данном конкретном случае, тебе нужны не ссылки и не указатели, тебе нужны итераторы
Код: (C++)
class A
{
public:
  int x;
  int y;
  A(int x, int y) : x(x), y(y) { };
};

typedef std::map<int, A*> ACollection;

class B
{
  ACollection list;
public:
  typedef ACollection::iterator Iterator;
  typedef ACollection::const_iterator CIterator;
public:
  CIterator a(int index) const;
};

CIterator B::a(int index) const
{
  return list.find(index);
}
 
Записан

Странно всё это....
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 13-12-2010 05:07 » 

Какое преимущество это даст?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 13-12-2010 08:08 » 

Некоторое неудобство использования итераторов:

Код: (C++)
it->second->method();

ptr->method();
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 13-12-2010 08:11 » 

а я вот так делаю, когда много обращений
Код:
MYTYPE& m=it->second;
m.method();
m.method2();
m.method3();
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 13-12-2010 08:24 » new

Леш, тогда проще сразу "const Type &" возвращать...
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 13-12-2010 08:37 » 

да нет разницы. С итератором даже лучше - так как может first тоже понадобиться
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 13-12-2010 08:38 » 

Я для удобства все таки этот индекс храню и в самом объекте.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 13-12-2010 08:52 » 

ну, я тоже, кстати )
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #17 : 13-12-2010 12:24 » 

итератору множно делать  ++ и --
можно проверить на конец данных при движении в любую сторону
можно передавать в стандартные алгоритмы
ну и да у итератор мапы не сильно удобный
Записан

Странно всё это....
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 13-12-2010 14:45 » 

В том то и дело, что получая нечто по индексу совсем не нужно никуда перемещаться. Видимо лучше все же указатель или ссылку.
Вопрос темы возвращается: что лучше использовать для возвращаемого значения?...
Думаю, что для монотонности интерфейса лучше ссылку.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 13-12-2010 14:50 » 

Когда возвращаешь указатель, можно вернуть 0, это скажет о невозможности выдачи указателя. А со ссылкой придётся возвращать bool
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #20 : 13-12-2010 14:54 » 

Лучше не специальное значение возвращать, а бросить исключение. Иное допускаю только на методах, которые специально проверяют возможность действия. Хотя, если почитать классиков, и тут можно использовать исключения.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 13-12-2010 15:54 » 

эээ, зачем ещё исключения, когда проще проверить на 0 ? Улыбаюсь
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #22 : 13-12-2010 17:24 » 

у меня дурацкий вопрос, если доступ по индексу, то зачем нужен map ?
Записан

Странно всё это....
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #23 : 13-12-2010 18:41 » 

Так индекс - первый параметр map. Т.е. в объекте хранится коллекция однотипных элементов с уникальными индексами, по которым их выбирают по одному. Также треба выбирать все элементы - на этот случай я завел пару функций, возвращающих пару итераторов.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #24 : 14-12-2010 04:42 » 

Так индекс - первый параметр map. Т.е. в объекте хранится коллекция однотипных элементов с уникальными индексами, по которым их выбирают по одному. Также треба выбирать все элементы - на этот случай я завел пару функций, возвращающих пару итераторов.
Так индекс - первый параметр map. Т.е. в объекте хранится коллекция однотипных элементов с уникальными индексами, по которым их выбирают по одному. Также треба выбирать все элементы - на этот случай я завел пару функций, возвращающих пару итераторов.

map ассоциативный контейнер с временем доступа к элементу O(log n)
если у тебе есть все элементы от 1 до N, то тебе map явно не нужен, тебе нужен вектор или deque
если набор разреженный, т.е. есть элементы с ключами 1, 2, 5, а 3 и 4 нет, то да тут нужен map
если у тебя ключ это число, то лучше посмотреть в строну hash_map

Далее, у тебя есть возражения насчёт итереторов
указатели не дадут возможность построить диапозон, их нельзя передать в стандартные алгоритмы, в твоём случае по ним можно получить доступ к одному элементу и всё, больше с ними ничего не сделаешь.
Если тебе не нравится итератор map из-за его дебильно first/second, то напиши свой итератор, который обладает нужным поведением, сохраняя поведение итератора map, благо это не сложно
Код: (C++)
template <typename TIter = map::iterator>
class Iterator
{
  TIter iter_;
public:
    typedef TIter::key_type TKey;
    typedef TIter::mapped_type TValue;
    TKey Key() {return iter_->first; }
    TValue & operator->() { return iter_->second; }
    // далее опиши всякие ++/--/== если они тебе нужны для работы диапозонов например
    // будет полезно перегрузить оператор *
}
если нужно просто получить доступ к элементу, пользуешься как обычным указателем, если нужно вытащить ключ используешь метод Key
« Последнее редактирование: 14-12-2010 04:47 от Антон (LogRus) » Записан

Странно всё это....
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #25 : 14-12-2010 04:49 » 

Индексы не 1..N, а уникальные идентификаторы из БД. Соотв., номера произвольные, разреженность произвольная.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines