Автор Тема: C++ инициализация ссылок  (Прочитано 57285 раз)

DddIzer

  • Гость
Re: C++ инициализация ссылок
« Ответ #135 : Март 28, 2013, 06:55:09 pm »
лично я вижу здесь одно - Берсеркер пытается  хакнуть stl... вне зависимости от результата, имхо,  не джедайское это дело...

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: C++ инициализация ссылок
« Ответ #136 : Март 28, 2013, 06:56:47 pm »

Разыменование является нормальным явлением.
и итераторов в частности?
Да, это естественный путь достать объект из контейнера. Других путей, в общем случае, пожалуй и нет.

(разименовывание итератора -- это не разименовывание указателя! это высокоуровневая операция!)
Y = λf.(λx.f (x x)) (λx.f (x x))

DddIzer

  • Гость
Re: C++ инициализация ссылок
« Ответ #137 : Март 28, 2013, 07:05:12 pm »

Разыменование является нормальным явлением.
и итераторов в частности?
Да, это естественный путь достать объект из контейнера. Других путей, в общем случае, пожалуй и нет.

(разименовывание итератора -- это не разименовывание указателя! это высокоуровневая операция!)
я имею ввиду ручное разименование?

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: C++ инициализация ссылок
« Ответ #138 : Март 28, 2013, 07:09:38 pm »

Разыменование является нормальным явлением.
и итераторов в частности?
Да, это естественный путь достать объект из контейнера. Других путей, в общем случае, пожалуй и нет.

(разименовывание итератора -- это не разименовывание указателя! это высокоуровневая операция!)
я имею ввиду ручное разименование?

Кажется я запутался в твоей путанице терминологий :-)
Давай на примере:
list<int> some_list;
i = find(some_list.begin(), some_list.end(),42);
if (i!=some_list.end()) cout << *i;
Такое - абсолютно корректно. Тут i - это ни разу не указатель.
Y = λf.(λx.f (x x)) (λx.f (x x))

Berserker

  • Sr. Member
  • ****
  • Сообщений: 254
    • Просмотр профиля
Re: C++ инициализация ссылок
« Ответ #139 : Март 28, 2013, 07:23:54 pm »
Цитировать
Не понял, где ты что-то писал про сплошные блоки памяти?
Цитировать
Нет, итератеры не сделаны через указатели :-) И пусть тебя не смущает разименовывание и стрелочки для доступа к потрохам - это обычные объекты :-) Каждый указатель можно трактовать как итератор, но не каждый этератор является указателем. Вообще, с точки зрения С++, указатели - это такие кривые и недоделанные, кастрированные, итераторы.
Да, речь идёт о контейнерах со сплошным хранением элементов. И здесь я имел в виду физическую реализацию, когда итератор является структурой, содержащей один указатель и нет проверок времени исполнения на выходы за границы контейнера.

Не редко вижу в ответах фразы "In fact, vectors iterators are usually implemented as pointers.", но не проверял итераторы в исходниках STL. Хотя более чем уверен, либо просто указатель, либо структура из одного поля с набором требуемых inline-операторов.

Цитировать
Итого ограничения: пустой контейнер (то есть empty() выдает true), и вызов для него find. Пустой map, list и vector (у которого что-то там унутре зарезервировано) -- вполне подходят.

Буду краток.

Цитировать
Нет, итератеры не сделаны через указатели :-)
Там, где возможно, сделаны. Например, в векторах. В случае списков возвращается адрес узла, у которого переопределена операция (*). Но вот незадача, содержимое элемента хранится в самом узле, а значит, после того, как end() вернул мусор, мы получили ссылку на мусор. Ссылки на мусор гораздо разрушительнее по последствиям, но это не являлось темой обсуждения. Я просто показал, насколько всё низкоуровнево внутри ради достижения эффективности.

По поводу возможности встраивания STL в сам язык и других предложений — это не ко мне, а к энтузиастам-разработчиком и гипотетическим будущим реализаторам STL.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: C++ инициализация ссылок
« Ответ #140 : Март 28, 2013, 07:34:49 pm »
Там, где возможно, сделаны. Например, в векторах. В случае списков возвращается адрес узла, у которого переопределена операция (*). Но вот незадача, содержимое элемента хранится в самом узле, а значит, после того, как end() вернул мусор, мы получили ссылку на мусор. Ссылки на мусор гораздо разрушительнее по последствиям, но это не являлось темой обсуждения.
Это зависит от реализации же! Контейнеры вполне могут резирвировать для end'а объект-заглушку. Вот вообще как нефиг делать (более того, подозреваю что в дебажном коде это так и делается, например в мелкософфтоффской реализации stl'я).

Еще раз - что там как унутре хранится в конкретной реализации может быть интересно ну только в очень специфических случаях. Полагаться можно только на то, что прописано в стандарте. Все. Точка.

Изучение языка ковыряясь в байтиках сгенерированных конкретной реализацией не даст понимания языка, в лучем случае даст понимание как иногда работает данная конкретная реализация языка (но при выходе следующей версии этой реализации программы могут просто перестать работать!).

Да.. А потом к нам приходят на собеседование люди с резюме, где в графе "языки программирования" гордо красуется нечто вроде: VisualC++. Но бывает конечно хуже - в графе написано C++, а знает он только Microsoft Visual C++ 2005 под x86 (32 бита). При этом языка не знает, и писать код так чтобы он был без UB (то есть работал всегда и везде, с любой валидной реализацией stl, компилятора и так далее) не умеет. Пичаль...

Я просто показал, насколько всё низкоуровнево внутри ради достижения эффективности.
Весь stl написан крайне высокоуровнево, но при этом он близок к железу. Следует одно от другого таки отличать :-)

По поводу возможности встраивания STL в сам язык и других предложений — это не ко мне, а к энтузиастам-разработчиком и гипотетическим будущим реализаторам STL.
Я к тому, что это явно прописано в стандарте, то есть возможность такого.
Y = λf.(λx.f (x x)) (λx.f (x x))

DddIzer

  • Гость
Re: C++ инициализация ссылок
« Ответ #141 : Март 28, 2013, 07:37:01 pm »

Такое - абсолютно корректно. Тут i - это ни разу не указатель.
не понял, в общем случае операция разименования перекрывается или нет?

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: C++ инициализация ссылок
« Ответ #142 : Март 28, 2013, 07:48:58 pm »

Такое - абсолютно корректно. Тут i - это ни разу не указатель.
не понял, в общем случае операция разименования перекрывается или нет?
Да. Можно написать свой класс который будет иметь операцию разименовывания.

Выглядит это как-то так:
struct Foo {
    int operator*(){return 42;}
};

Естественно оператор разименовывания не обязан возвращать именно int.
Y = λf.(λx.f (x x)) (λx.f (x x))

Berserker

  • Sr. Member
  • ****
  • Сообщений: 254
    • Просмотр профиля
Re: C++ инициализация ссылок
« Ответ #143 : Март 28, 2013, 07:52:15 pm »
Ну вот, Алексей, мы и пришли к заключению. Вы, вероятно, знаете множество реализаций STL для C++. Мой опыт гораздо более скромный. И это скромный опыт говорит, что в STL ради оптимизации везде, где можно, в качестве итераторов используются указатели. Это первое. И второе: нет множества проверок времени исполнения, которые бы гарантировали безопасность контейнеров как абстрактных типов данных. Вместо этого там грабли и грабли.

Я не вижу ничего плохого в том, чтобы знать, где могут быть причины ошибок. Понимание наиболее вероятного варианта реализации позволяет как самому создавать новые реализации, так и ориентироваться в существующих, ну и, разумеется, при отладке. А если на работу не возьмёте, так уж и быть, не обижусь ;)

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: C++ инициализация ссылок
« Ответ #144 : Март 28, 2013, 08:01:43 pm »
Ну вот, Алексей, мы и пришли к заключению. Вы, вероятно, знаете множество реализаций STL для C++. Мой опыт гораздо более скромный. И это скромный опыт говорит, что в STL ради оптимизации везде, где можно, в качестве итераторов используются указатели. Это первое. И второе: нет множества проверок времени исполнения, которые бы гарантировали безопасность контейнеров как абстрактных типов данных. Вместо этого там грабли и грабли.
Ну, кое-что все же есть. Например at() вместо [] для вектора. И будет вам проверка выхода за границы дозволенного :-)

Ну, кроме того, в каждой конкретной реализации обычно есть волшебные ключики которые врубают рантаймовые проверки всего чего можно и нельзя. Ну тормозит (относительно безключевого), зато безопасно и столь же "быстро" как в языках с проверками.

Ну и наконец - никто не мешает нарисовать удобную для тебя обертку над всем этим, которая сама будет проверять на end().

Я не вижу ничего плохого в том, чтобы знать, где могут быть причины ошибок. Понимание наиболее вероятного варианта реализации позволяет как самому создавать новые реализации, так и ориентироваться в существующих, ну и, разумеется, при отладке. А если на работу не возьмёте, так уж и быть, не обижусь ;)
А я на работе на С++ и не пишу практически, так что С++'сник мне никак не нужен :-) Вот от жабоскриптоведа/html-профи я бы не отказался :-) Ну и есть задачи на Go и матлабе, а также на ObjC&C99.

А для того, чтобы знать какие могут быть причины ошибок - нужно таки стандарт (ну или хотя бы более человеческое описание на cppreference.com да www.cplusplus.com/reference/) читать - там написано. Из реализации эти знания выколупывать - занятие не благодарное абсолютно (да еще и ответ может быть не верным).
Y = λf.(λx.f (x x)) (λx.f (x x))

Berserker

  • Sr. Member
  • ****
  • Сообщений: 254
    • Просмотр профиля
Re: C++ инициализация ссылок
« Ответ #145 : Март 28, 2013, 08:08:30 pm »
Читаю всё вместе: критику языка (лучшее в сети — Defective C++ или C++ FQA), cppreference, ответы на stackoverflow ну и отладчик с исходниками STL забывать не стоит. Так сказать, для полноты картины  8)

Однако когда речь идёт о коде, я всегда предпочитаю представлять перед собой то, что стоит за абстракциями. Иногда вплоть до команд. Судя по тому, как пишутся чувствительные к производительности вещи, не только у меня подобное восприятие.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: C++ инициализация ссылок
« Ответ #146 : Март 28, 2013, 08:23:08 pm »
Читаю всё вместе: критику языка (лучшее в сети — Defective C++ или C++ FQA), cppreference, ответы на stackoverflow ну и отладчик с исходниками STL забывать не стоит. Так сказать, для полноты картины  8)

Однако когда речь идёт о коде, я всегда предпочитаю представлять перед собой то, что стоит за абстракциями. Иногда вплоть до команд. Судя по тому, как пишутся чувствительные к производительности вещи, не только у меня подобное восприятие.
Чувствительные к производительности вещи обычно таки имеют довольно узкую нишу в плане железа (иначе нужной производительности не достичь) и там свой подход. Вплоть до выкидывания текущей реализации stl и написания своего велосипеда под особенности задачи, железа, компилятора и операционки.

Ну, например если у меня задача такова, что мне кроме линукса и gcc на нем никто не нужен, да к тому же задача требует множества конкурентных нитей, то я вполне могу заюзать бесконечный растущий системный стек в виде двусвязного списка чанков для каждой из нити и получить с этого немалый профит.

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

Ну, то есть хорошо бы неплохо уже знать сам язык чтобы легко видеть границу между стандартом на язык (что гарантирует что оно будет вот так работать, не работать или вообще UB везде), реализацией языка, фичами которые навешиваются на язык конкретными реализациями вопреки стандарту, и условиями которые определяет среда исполнения (операционка, железка и так далее).

PS. А еще есть http://isocpp.org/
Y = λf.(λx.f (x x)) (λx.f (x x))

DddIzer

  • Гость
Re: C++ инициализация ссылок
« Ответ #147 : Март 29, 2013, 04:24:56 am »

Такое - абсолютно корректно. Тут i - это ни разу не указатель.
не понял, в общем случае операция разименования перекрывается или нет?
Да. Можно написать свой класс который будет иметь операцию разименовывания.

Выглядит это как-то так:
struct Foo {
    int operator*(){return 42;}
};

Естественно оператор разименовывания не обязан возвращать именно int.
как переопределяются операторы я знаю.. меня интересуют другой вопрос.. - в самой stl - перекрывается оператор разименования или это дело исключительно обьекта который помещается в контейнер.

DddIzer

  • Гость
Re: C++ инициализация ссылок
« Ответ #148 : Март 29, 2013, 04:32:45 am »
Читаю всё вместе: критику языка (лучшее в сети — Defective C++ или C++ FQA), cppreference, ответы на stackoverflow ну и отладчик с исходниками STL забывать не стоит. Так сказать, для полноты картины  8)

Однако когда речь идёт о коде, я всегда предпочитаю представлять перед собой то, что стоит за абстракциями. Иногда вплоть до команд. Судя по тому, как пишутся чувствительные к производительности вещи, не только у меня подобное восприятие.
желание хакать неистребимо... гораздо труднее приучить себя писать инвариантно относительно особенностей реализации.. - ибо, на первый взгляд , это всегда 100% оверхед и потери в производительности, кроме того всегда приятно переложить часть ответственности на создателей копмилятора и яп (дескать буду использовать адресную арифметику и писать хитрожопые выражения с  инкрементальными операторами ... и все будет за..сь).. дескать они люди заведомо более вумные , коль скоро создали такую похерень, как С++... -так что единомышленниками вы , Berserker, обделены никогда не будете... :).
« Последнее редактирование: Март 29, 2013, 04:35:21 am от DddIzer »

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: C++ инициализация ссылок
« Ответ #149 : Март 29, 2013, 03:50:08 pm »

Такое - абсолютно корректно. Тут i - это ни разу не указатель.
не понял, в общем случае операция разименования перекрывается или нет?
Да. Можно написать свой класс который будет иметь операцию разименовывания.

Выглядит это как-то так:
struct Foo {
    int operator*(){return 42;}
};

Естественно оператор разименовывания не обязан возвращать именно int.
как переопределяются операторы я знаю.. меня интересуют другой вопрос.. - в самой stl - перекрывается оператор разименования или это дело исключительно обьекта который помещается в контейнер.

В stl у каждого типа итераторов перекрыт оператор разименовывания - итератор это отдельный, обобщенный тип (struct обычно), не завязанный вообще говоря, на тип того что там в контейнере будет храниться.

Перекрыто что-то у тех кто будет в контейнерах храниться или нет - никого не волнует.
Y = λf.(λx.f (x x)) (λx.f (x x))