考虑以下代码:
#include <iostream>
void f(int const& a, int& b)
{
b = a+1;
}
int main() {
int c=2;
f(c,c);
std::cout << c << std::endl;
}
f
接受两个引用类型参数:int const& a
和int& b
。因此,f
不应该修改a
,但是可以修改b
,实际上它确实这样做了。- 然而,在
main
函数中,我传递了同一个变量,分别由a
和b
引用。由于f
修改了b
,也就修改了a
,尽管不应该这样做。
这段代码编译时没有任何警告,并打印出3
。如果我们单独跟踪每个变量,看起来const正确性得到了尊重:c
是非const的,因此将其作为a
的const
引用以及作为非const引用的b
是完全可以的,在f
函数体内修改b
(非const),同时不触及const的a
。然而,当c
被同时用作a
和b
时,在f
函数体内修改了a
,违反了a
是const的假设,即使没有明确调用const_cast
。
我尽可能简化了这个例子,但人们很容易想到不太明显的用例(例如在非const引用参数上执行const方法)。
我的问题是:
- 我们真的可以说上面的代码是const正确的吗?
- 上述用例是已知的模式吗?它被认为是一种不良实践吗?
- 除了对读者来说令人困惑外,上述代码还可能是技术问题的源头吗?例如未定义的行为或编译器进行错误的简化假设?
c = f(c);
看起来会很奇怪吗? - Fred Larsonf()
,const
的正确性是可以的。它做到了它承诺的不修改a
并修改b
。滥用发生在main()
中(对于a
和b
使用同一变量)。你还能做什么:在f()
中检查&a != &b
,并/或在f()
的文档中标注相应的约束(如果必要)。 - Scheff's Catb
的值将简单地是2,它将用于计算,结果将是b=5
。我本可以写成b=3
,我的问题仍然是一样的,我只是写了a+1
,以便编译器不会抱怨未使用的变量。 - Gabriele Buondonno