Я пишу библиотеку, которая позволяет строить байесовские сети. Структура сети инкапсулируется, и пользователь не может получить доступ к своим полям; однако они могут получить и установить некоторые из них. Предположим, вы хотите написать функцию доступа для поля table
(который в основном представляет собой двойной массив), например. Между следующими вариантами, что было бы более уместным?Как определить функцию геттера
Первый вариант:
int getTable(Net *net, double *res)
Второй вариант:
double *getTable(Net *net)
В первом варианте, пользователь предоставляет указатель на массив, где будут записаны значения таблицы. Функция копирует значения таблиц на res
, оставляя пользователя без прямого доступа к внутренней структуре. Изменение res
оставляет таблицу сети неизменной. Конечно, для правильного выделения res
предусмотрена другая функция (скажем getTableSize()
). Это кажется безопасным (внутренняя структура остается согласованной) и имеет то преимущество, что вы можете вернуть значение кода, если что-то пойдет не так. Недостатком является то, что этот подход может быть медленнее, чем следующий, поскольку он включает в себя копию. Как правило, количество значений table
может варьироваться от 1 до нескольких сотен.
Во втором варианте функция возвращает непосредственно указатель на внутренние значения. В документе я укажу, что пользователь не может попытаться освободить указатель или изменить значения. Освобождение указателя может привести к ошибке сегментации и утечке памяти, если выполняются другие операции в сети. Изменение таблицы не приведет к какой-либо видимой ошибке, но внутренняя когерентность будет нарушена, и результаты последующих вычислений могут быть очень неправильными и очень трудными для отладки для пользователя.
Какой вариант вы предпочитаете? Что еще нужно рассмотреть? Есть ли другой подход?
Я бы взял прежний подход. Пользователь этой библиотеки может иметь свои предпочтения в отношении распределения динамической памяти (например, не использовать ее вообще). –
ИМО оба подхода имеют свое место на основе требуемой семантики. первый подход заслуживает того, чтобы быть безопасным из-за того, что он не подвергался внутреннему воздействию, но второй подход был бы полезен, например, для функции pop для структурирования данных контейнера – ForeverStudent