Там, где возможно, сделаны. Например, в векторах. В случае списков возвращается адрес узла, у которого переопределена операция (*). Но вот незадача, содержимое элемента хранится в самом узле, а значит, после того, как end() вернул мусор, мы получили ссылку на мусор. Ссылки на мусор гораздо разрушительнее по последствиям, но это не являлось темой обсуждения.
Это зависит от реализации же! Контейнеры вполне могут резирвировать для end'а объект-заглушку. Вот вообще как нефиг делать (более того, подозреваю что в дебажном коде это так и делается, например в мелкософфтоффской реализации stl'я).
Еще раз - что там как унутре хранится в конкретной реализации может быть интересно ну только в очень специфических случаях. Полагаться можно только на то, что прописано в стандарте. Все. Точка.
Изучение языка ковыряясь в байтиках сгенерированных конкретной реализацией не даст понимания языка, в лучем случае даст понимание как иногда работает данная конкретная реализация языка (но при выходе следующей версии этой реализации программы могут просто перестать работать!).
Да.. А потом к нам приходят на собеседование люди с резюме, где в графе "языки программирования" гордо красуется нечто вроде: VisualC++. Но бывает конечно хуже - в графе написано C++, а знает он только Microsoft Visual C++ 2005 под x86 (32 бита). При этом языка не знает, и писать код так чтобы он был без UB (то есть работал всегда и везде, с любой валидной реализацией stl, компилятора и так далее) не умеет. Пичаль...
Я просто показал, насколько всё низкоуровнево внутри ради достижения эффективности.
Весь stl написан крайне высокоуровнево, но при этом он близок к железу. Следует одно от другого таки отличать :-)
По поводу возможности встраивания STL в сам язык и других предложений — это не ко мне, а к энтузиастам-разработчиком и гипотетическим будущим реализаторам STL.
Я к тому, что это явно прописано в стандарте, то есть возможность такого.