а про целостность и удобство
Если уж возвращаться к оригинальному заголовку темы, то меня интересовал лишь один вопрос: почему ссылки нельзя изменять? Выяснилось, что физически компиляторы изменение поддерживают, а запрет возник из-за прихоти создателя языка и не имеет под собой никаких оснований.
Очевидно, что это не так.
Во-первых: я явно привел пример когда видно, что внутренняя реализация ссылок и указателей может быть различна - в случае gcc у них разные UB в случае const_cast'a.
Во-вторых: аргументы влада.
В-третьих: ссылка гарантирует что переменная валидна. Никаких нулей.
После этого поступили возражения по поводу того, что ссылки — это псевдонимы и что их в принципе менять нельзя, что, конечно же, неправда. Именно поэтому я был вынужден спуститься ниже и напомнить, что ссылки всё же указатели на физическом уровне, а возможность установки единожды используется компилятором исключительно для оптимизаций. Пример такой оптимизации локальных ссылок Вы и привели, Алексей.
Я не очень понимаю различие между реализацией и, гм, оптимизацией реализации :-) В принципе полагаю возможно как минимум часть семантики (если не всю семантику) ссылок реализовать через простое копирование объекта (без вызовов конструкторов, тупо memcpy). И это не будет противоречить стандарту.
Я просто прошу взглянуть свежим и трезвым взглядом на проблему. Правило одного присваивания — это сфера функциональных языков, не имеющая смысла в императивных.
Эмм.. Что за домыслы? Иммутабельность естественно имеет смысл в императивных языках. Функциональность довольно таки ортогональна иммутабельности :-) Впрочем, задам ка я вопрос - какое основное отличие функционального языка от императивного? Вот прям основное-основное.
То есть если X — это ссылка на объект типа файловой системы, то никакой причины запретить динамически подменять реализацию файловой системы нет.
Э? При чем тут реализация?
Я даже скажу более, ссылка — не псевдоним с логической точки зрения.
vector<int> &a = rand() % 100 >= 50 ? b : c;
Это чистой воды ветвление. Почему же нельзя использовать if/else?
Конечно это ветвление. И конечно же это не отменяет тот факт, что "a" тут является псевдонимом как и обычно :-) some& foo = expr; -- тут foo является псевдонимом для результата выражения expr. const int& foo = 42; -- частный случай этого. Тут просто выражение тривиально. Кто сказал что псевдонимы могут быть только детерминированными? :-)
Тернарный оператор - это выражение, так что не вижу никаких противоречий. А вот if..else - это зачем-то statement. Поэтому увы-с, не взлетит.
Ну и напоследок. Изменение ссылок не влияет на их свойство быть не NULL (хрупкое, конечно, но свойство).
Покажи пожалуйста, ну, например на примере java, как ты собираешься бороться с нулями в изменяемых ссылках. То есть чтобы гарантированно, и не зависило от кривости рук программера.
Ну, например на том же примере твоем: vector<int> &a = rand() % 100 >= 50 ? b : c;
Пусть тут будет: 1) if..else. 2) не будет лишних инициализаций.
Кстати, те же итераторы сделаны через указатели. Не сложно вызвать какой-нибудь find на пустой коллекции, разыменовать его и привязать объект к ссылке. Будет чистой воды NULL-ссылка в самом что ни на есть корректном коде.
Нет, итератеры не сделаны через указатели :-) И пусть тебя не смущает разименовывание и стрелочки для доступа к потрохам - это обычные объекты :-) Каждый указатель можно трактовать как итератор, но не каждый этератор является указателем. Вообще, с точки зрения С++, указатели - это такие кривые и недоделанные, кастрированные, итераторы.
А то что ты описал - не будет NULL-ссылкой. Будет UB чистой воды (причем по двум разным причинам одновременно). И нет, это не корректный код. :-)