Есть ли смысл делать struct неизменной? - PullRequest
0 голосов
/ 03 февраля 2019

Так как я пришел в C из Java более высокого уровня, где у нас нет типизаторов типа const, чтобы сделать тип неизменяемым, мы должны объявить все его члены окончательными и убедиться, что члены сами по себе неизменны.

По контракту, в C у нас есть тип-квиализатор const.

Чтобы быть более конкретным, позвольте мне привести пример, с которым я сейчас застрял.У меня есть следующее

application.h:

struct application_config_t{
    int poll_interval;
    int compression_ratio;
    //other config parameters
};

struct application_t{  //This structure make me confused
    void (*run_application)(struct application_t*);
    void (*stop_application)(struct application_t*);
};

struct application_t* create_app(const struct application_config_t);
void release_app(struct application_t*);

Я не уверен, как определить структуру application_t.Его единственная цель - выполнить актуальный запуск с run_application и обработать SIGINT с помощью stop_application, чтобы выполнить постепенное отключение, а затем после stop_application вернуться к вызову release_app(struct application_t*), чтобы освободить память.

У меня есть следующий случай на выбор:

I .Неизменный application_t

struct application_t{
    void (*const run_application)(struct application_t*);
    void (*const stop_application)(struct application_t*);
}

Я думаю, что это нормально, потому что созданное приложение не должно изменяться.Но создание такой неизменной структуры повлечет за собой memcpy вызов в любом случае ...

II .Изменяемый application_t при создании приложения будет объявлен как

const struct application_t* create_app(const struct application_config_t);

Это было бы хорошо, но я хочу освободить память, на которую указывает struct application_t* после возврата stop_application.Отпускание struct application_t* означает, что appliaction_t на самом деле не const.И использование как

struct application_config_t cfg;
//...
const struct application_t *app_ptr = create_app(cfg);
(app_ptr -> run_application)(app_ptr);
release_app((struct application_t *) app_ptr); //const cast

потребует приведения против const ness.

1 Ответ

0 голосов
/ 03 февраля 2019

Выпуск struct application_t * означает, что appliaction на самом деле не является константой

На самом деле это так.Код клиента не может изменить его, и его не следует использовать после передачи в любом случае release_app.Это const в течение всего времени жизни, и если release_app принимает указатель на const, это будет семантически правильно (просто выполните приведение внутри release_app).

Почему я говорю, что это будетсемантически правильно?Потому что, когда create_app выделяет пространство для структуры и инициализирует ее, это не const, не так ли?const добавляется позже как часть контракта.Таким образом, принятие константного указателя в release_app просто следует тому же контракту, который вы уже установили.Тот факт, что пара API знает, что хранилище может быть изменено, не нарушает контракт.

...