А что, на функцию может быть не только указатель, но и ссылка?

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

а использовать уже в стиле языка С++ (передавать параметры через ссылки).
Ну сейчас можно использовать всюду std::function и не сношать себе мозг. В блоге разработчиков Visual C++ написано что каждый раз когда они вносят очередную хорошую оптимизацию в std::function из отдела разработки MS Office им присылают тортик, так как std::function в коде новых оффисов используется почти в каждом классе. Так что этот класс вылизан очень хорошо. В gcc оверхед от std::function - всего две дополнительные инструкции CPU ни один вызов. Лично меня удивляет что настолько полезного класса не было в С++98. Это был эпический факап.
2B OR NOT(2B) = FF
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Absurd писал(а):На этапе компиляции никаких адресов не существует.
Что, и смещений локальных автоматических переменных от вершины стека не существует? То, что они не собраны в окончательный вид, ещё ничего не значит.
Absurd писал(а): Если действительно нужно передать каллбэк безопасно это можно сделать при помощи шаблона если интерфейс класса не виртуальный и можно вынести все тело функции принимающей каллбэк в .h файл.
Кого ещё можно так вынести? Стдкол? Или может паскалевское соглашение о вызовах? При чём здесь эта тема?
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Absurd писал(а): Если действительно нужно передать каллбэк безопасно это можно сделать при помощи шаблона если интерфейс класса не виртуальный и можно вынести все тело функции принимающей каллбэк в .h файл.
Кого ещё можно так вынести? Стдкол? Или может паскалевское соглашение о вызовах? При чём здесь эта тема?
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Что, и смещений локальных автоматических переменных от вершины стека не существует?
Функции располагаются не в сегменте стека, а в сегменте кода. Конкретное смещение знает только линковщик, и то не всегда и не везде. Есть также COFF/ELF relocation tables.
Если действительно нужно передать каллбэк безопасно это можно сделать при помощи шаблона если интерфейс класса не виртуальный и можно вынести все тело функции принимающей каллбэк в .h файл.
Кого ещё можно так вынести? Стдкол? Или может паскалевское соглашение о вызовах? При чём здесь эта тема?
Такой шаблон не зависит от формата вызова. Ему можно передать __stdcall, member function pointer, С++11 lambda, и пр.
2B OR NOT(2B) = FF
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Функции располагаются не в сегменте стека, а в сегменте кода.
А я прям не знаю. Вот только переменные, даже локальные, - это всё таки не функции. А линковщик знает несколько другие смещения - смещения функций, статических переменных и глобальных переменных от базового адреса исполняемого файла. Но смещения от вершины стека - внутреннее дело каждой функции, хоть сами данные по этим смещениям и не часть её. Но эти данные - её собственность. И выталкивать их на этап линковки совершенно не обязательно, даже если какой то уникум так и сделал.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

А я прям не знаю. Вот только переменные, даже локальные, - это всё таки не функции.
Только речь в треде идет о функциях.
2B OR NOT(2B) = FF
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Параметры и операнды - это переменные, а не функции. Даже если среди них и валяются ссылки на функции. Эти ссылки - не синонимы, а синтаксический прибамбас, в который завёрнуты указатели.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Параметры и операнды - это переменные, а не функции. Даже если среди них и валяются ссылки на функции. Эти ссылки - не синонимы, а синтаксический прибамбас, в который завёрнуты указатели.
Все ссылки это синтаксический прибамбас для указателей. Кроме того, с точки зрения компилятора все указатели это синонимы, что усложняет генерацию кода.

Код: Выделить всё

int foofunc() {
  int *a = foo();
  int *b = bar();  
  *a += 10;  
  return *a + *b;
}
Если ты попытаешься написать коспилятор Си (*), то ты поймешь что в общем случае невозможно определить a или b во время выполнения будут равны или не равны. Поэтому компилятор С всегда исходит из пессимистического предположения что они могут быть равны. То есть с точки зрения компиляторов Си и Си++ *a и *b это вероятные синонимы и изменение одного может повлечь изменение другого, поэтому любое изменение порядка операций здест противопоказано даже если оно позволит более оптимально уложить инструкции на входной конвеер процессора. Ссылки в этом отношении ничем не отличаются. Чтобы решить эту проблему в С99 внесли квалификатор __restrict. Существуют также оптимизации связанные с предположением что указатели char* a и int* b всегда будут указывать на непересекающиеся диапазаоны адресов (т.н. strict aliasing rules). Эти оптимизации ломают топорные конверсии типов вроде int->char[sizeof(int)] при помощи указателей.

*) это несложно, добросовестный студент компьютерно-математической специальности может его написать запросто в одиночку за несколько недель, особенно если будет писать на перле или питоне. Хороший этюд для программиста, кстати. Из нетривиального тут только маппинг переменных на регистры который сводится к классической задаче о раскраске вершин графа минимальным количеством цветов, для которой придуманы вполне быстрые, точные и несложные алгоритмы. Если не мапить и заливать регистры заново значениями из стека с последующей заливкой результата обратно в стек для каждой примитивной операции все будет работать, только код получится неоптимальный со скоростью на уровне хороших скриптовых языков. Можно не заморачиваться с генерацией *.obj и *.exe, а генерировать текст с ассемблерным листингом и передавать его внешнему ассемблеру.
2B OR NOT(2B) = FF
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Absurd писал(а):Все ссылки это синтаксический прибамбас для указателей.
В каком месте стандарта это сказано? Другое дело, что это - возможный вариант реализации не только ссылочных параметров и ссылочных операндов, но и вообще всех ссылок. А можно все ссылки кроме ссылочных параметров, ссылочных операндов, значений возвращающих ссылки функций и значений возвращающих ссылки операторов, включая оператор разыменования (он ведь тоже по сути возвращает именно ссылку), заменять идентификаторами тех сущностей, на которые они ссылаются даже до основного прохода компиляции. Если это слишком сложно и не оптимально, то это ещё не повод утверждать, что все ссылки реализованы через указатели. стандарт такой реализации не гарантирует. Но когда на этапе разработки не известно, куда именно сошлётся ссылка, тогда да, тогда это синтаксическая надстройка над указателем, так как иная реализация не возможна. Можно предположить, что такая надстройка - единственная фактически применяемая реализация всех ссылок. Но стандарт говорит только синонимичности ссылок тому, на что они ссылаются и не конкретизирует реализацию.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

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

Код: Выделить всё

int x;
int *p=&x;
int &y=x;
x=20; // Здесь адрес находится в сегменте кода, конкретно в самом коде операции (цепочке кодов операций)
*p=30; // А здесь адрес непосредственно икса лежит в сегменте данных
y=40; // Здесь возможны оба варианта, стандартом гарантирован лишь результат, идентичный тому, как если бы ссылка была дефолтно разыменуемым указателем
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Ответить