Есть ли случаи, когда возврат структуры напрямую является хорошей практикой?
IMO весь код, который возвращает структуру напрямую, может быть изменен для возврата указателя на структуру.
Когда возвращение структуры напрямую является хорошей практикой?
6 ответов
Модифицированный как? Возврат указателя на статический экземпляр структуры внутри функции, что делает функцию не реентерабельной; или возвращая указатель на выделенную структуру кучи, которую вызывающая сторона должна обязательно освободить и сделать это соответствующим образом? Я хотел бы рассмотреть возвращение структуры, являющейся хорошей практикой в общем случае.
Самым большим преимуществом возврата полной структуры вместо указателя является то, что вам не нужно связываться с указателями. Избегая рисков, присущих указателям, особенно если вы выделяете и освобождаете собственную память, кодирование и отладка могут быть значительно упрощены.
Во многих случаях преимущества передачи структуры напрямую перевешивают недостатки (время / память) копирования всей структуры в стек. Если вы не знаете, что оптимизация необходима, нет причин не идти по более легкому пути.
Я рассматриваю следующие случаи, как те, которые я бы чаще всего выбирал для проходящих структур, непосредственно:
Код стиля "Функциональное программирование". Множество вещей передается, и наличие указателей сильно усложнит код (и это даже не считается, если вам нужно начать использовать malloc + free)
Маленькие структуры, как например
struct Point{ int x, y; };
не стоит тратить время на передачу информации по ссылке.
И, наконец, давайте не будем забывать, что передача по значению и передача по ссылке на самом деле очень разные, поэтому некоторые классы программ будут в большей степени соответствовать одному стилю и в конечном итоге будут выглядеть ужасно, если вместо них будет использоваться другой стиль.
Эти другие ответы хороши, но я думаю, что пропущенный наиболее близко подходит к "ответу на вопрос", упоминая небольшие структуры. Чтобы быть более конкретным, если сама структура имеет длину всего в несколько машинных слов, то и возражение "пространства", и возражение "времени" преодолеваются. Если указатель - одно слово, а структура - два слова, насколько медленнее операция копирования структуры по сравнению с копией указателя? Я подозреваю, что в кэшированной архитектуре ответ "ни один из всех". А что касается пробела, 2 слова в стеке < 1 слово в стеке + 2 слова (+ накладные расходы) в куче.
Но эти соображения подходят только для конкретных случаев: ЭТА часть ЭТОЙ программы на ЭТОЙ архитектуре.
Для уровня написания программ на C вы должны использовать то, что легче читать.
Если вы пытаетесь освободить побочный эффект от своей функции, прямой возврат структуры поможет, потому что она будет передаваться по значению. Это более эффективно? Нет, переход по ссылке происходит быстрее. Но отсутствие побочных эффектов может действительно упростить работу с потоками (общеизвестно трудная задача).
Есть несколько случаев, когда возвращение структуры по значению противопоказано:
1) Библиотечная функция, которая возвращает данные "токена", которые должны быть позже использованы в других вызовах, например. дескриптор потока файла или сокета. Возвращение полной структуры нарушит инкапсуляцию библиотеки.
2) Структуры, содержащие буферы данных переменной длины, где структура была рассчитана с учетом абсолютного максимального размера данных, но где средний размер данных намного меньше, например. структура сетевого буфера, в конце которой находятся dataLen int и char data[65536].
3) Большие структуры любого типа, где стоимость копирования данных становится значительной, например:
а) Когда структура должна быть возвращена через несколько вызовов функций - многократное копирование одних и тех же данных.
б) Когда структура впоследствии ставится в очередь в другие потоки - широкие очереди означают более длительное время блокировки во время копирования / копирования и, таким образом, повышают вероятность конфликта. Это и размер структуры накладываются на стеки потоков как производителя, так и потребителя.
в) где структура часто перемещается между слоями, например. стек протоколов.
4) где структуры разной должны храниться в любом массиве / списке / очереди / стеке /whatContainer.
Я подозреваю, что я настолько испорчен с ++ и другими ОО языками, что я склонен к тому, чтобы malloc / new почти все, что не может быть сохранено в нативном типе
Ргдс, Мартин