【问题标题】:Does it make any sense to make struct immutable?使结构不可变是否有意义?
【发布时间】:2019-06-27 07:27:01
【问题描述】:

自从我从高级 Java 来到 C 以来,我们没有像 const 这样的类型限定符来使类型不可变,我们必须将其所有成员声明为 final 并确保成员本身是不可变的。

按照约定,在 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 执行实际运行并使用stop_application 处理SIGINT 以执行正常关闭,然后在stop_application 返回后调用release_app(struct application_t*) 以释放内存。

我有以下情况可供选择:

。不可变application_t

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

我认为这很好,因为一旦创建应用程序就不应修改。但是创建这样一个不可变结构将需要memcpy 调用...

。可变的application_t,而创建应用程序将被声明为

const struct application_t* create_app(const struct application_config_t);

这很好,但我想在stop_application 返回后释放struct application_t* 指向的内存。释放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

需要对constness 进行强制转换。

【问题讨论】:

    标签: c struct constants


    【解决方案1】:

    释放 struct application_t* 意味着 appliaction 不是真正的 const

    其实是这样的。客户端代码无法对其进行变异,并且无论如何在将其移交给release_app 后都不应该进一步使用它。它在其整个生命周期内都是const,如果release_app 通过指向const 的指针接受,则它在语义上是正确的(只需在release_app 内进行强制转换)。

    为什么我说它在语义上是正确的?因为当create_app 为结构分配空间并初始化它时,那里不是const,是吗? const 稍后作为合同的一部分添加。因此,接受release_app 中的 const 指针只是遵循您已经建立的相同合同。 API 对知道存储可以改变这一事实并没有违反合同。

    【讨论】:

    • 因为 create_app 为结构分配空间并初始化它时,它不是 const ,是吗? 我有一个问题。如果我们声明const struct application_t* create_app(const struct application_config_t);void release_app(const struct application_t*);,我们将需要以下合同:“一旦应用程序创建,它在发布之前不能修改”这有意义吗?在这里create_app 返回const 防止它在创建后立即进行任何修改。
    • @SomeName - 这就是您想要的合同。至少我是这么读你的问题的。所以,是的,将其编入所涉及的类型是有意义的。我什至会更进一步说这样做没有意义。如果你只返回一个const application_t *,用户代码怎么可能获得指向非const版本的指针,除非以某种方式违反合同?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 2012-03-12
    • 1970-01-01
    相关资源
    最近更新 更多