如何处理子函数中的 const 传播

How to deal with const propagation in subfunctions

我需要对现有函数进行修改,具有一些 const 输入参数:

int f(const owntype *r1, const owntype *r2)

为此,我想调用一个使用相同类型但没有 const 关键字的子函数:

void subfunction (owntype *src, owntype *dst)

我已经尝试过这个(以及其他一些变体),但它不起作用:

int f(const owntype *r1, const owntype *r2) {
  ...
  subfunction((const owntyp*) r1);
  ...
}

如何在不更改两个函数的参数描述的情况下编译它?

(const owntype *)r1 是空操作,因为 r1 的类型已经是 const owntype *.

被调用的函数(subfunction())需要一个owntype *类型的参数。当将 r1 作为参数传递给 subfunction() 时,您可以将 r1 转换为 owntype *,但是如果 subfunction() 试图修改该值,那么您就有大麻烦了。

想一想这两个函数的接口。

int f(const owntype *r1, const owntype *r2)

说:"Give me the addresses of two owntype objects (r1 and r2) and I promise I won't change the objects (const)."

然后它在内部将 r1r2 传递给 subfunction()subfunction() 没有就其参数所指向的值做出任何承诺(那里没有 const),并且可以随意更改它们。然后 returns 和 f() 在不知情的情况下食言。

这不是事情的运作方式,这就是为什么从 const 转换为非 constundefined behaviour.

的原因

只要subfunction不尝试写入指向的对象*r1*r2就可以通过转换调用它:

subfunction(owntype*)r1, (owntype*)r2);

标准(§6.7.3)说:

If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.

所以,只要你不写入它,读取它就可以了。

最好的解决方案是修改 subfunction 以获取指向 const 的指针。

在实践中,有时这是不可能的(例如,需要修改由于组织惯例而不允许修改的代码)。在这些情况下你可以写:

subfunction( (owntype *)r1, (owntype *)r2 );

这是正确的,只要您确定 subfunction 不会修改指向的对象。如果它确实尝试修改它们,那么在尝试修改时将导致未定义的行为。

如果您不确定 subfunction 的作用,并且想进行防御性编程,那么另一种选择是复制对象:

owntype c1 = *r1, c2 = *r2;
subfunction( &c1, &c2 );

请注意,检查复制是否不会破坏 owntype 的 class 不变量。


其他一些 answers/comments 建议丢弃 const 可能是未定义的行为。然而事实并非如此。相关引用是C11 6.7.3/6:

If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.

Link to question on that topic

您已声明 subfunction 不会更改输入。这是 purpose/design 还是将来的更改可能会导致修改输入?

在第一种情况下,将输入定义为 not const 显然是一个错误。 由于 subfunction 似乎在您的控制之下:修复界面 -> 完成!

在第二种情况下(接口的 constness 被正确选择)还有:不要删除常量!对该函数的未来更改可能会在意想不到的地方破坏您的代码。而是制作一个本地副本并将副本用作 subfunction.

的参数

来自评论:

subfunction() does not modify the mentioned parameters, but it's widespread in the application, and at every place, a variable, not declared as const, is used for it. If I change the signature of subfunction(), I'll need to do modifications through the whole program, which I want to avoid.

请注意,向使用 const 参数定义的函数提供非常量参数是完全没问题的。因此,除非 subfunction 调用其他具有非常量参数的函数,否则如果将参数更改为 const.

它将正常工作

请注意,如果您想在现有代码中引入 const,最简单的做法是自下而上。从最基本的函数(那些不调用任何其他函数的函数)开始,然后逐步向上调用层次结构。这样你就可以一点一点地做。如果您从顶部开始(如 main 中),则代码将不会再次编译,直到您在所有地方都进行了更改。