考虑以下代码:
#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中,我传递了ame变量,由a和b引用。当f修改b时,它也修改了a,而它应该不应该修改
此代码编译时没有任何警告,并打印3。如果我们单独跟踪每个变量,看起来似乎尊重了常量正确性:c是非常数,因此将其作为constref作为a传递,也作为非常数ref作为b传递,并在f的主体内修改b,这是非常数,但不接触a,这是常量。但是,当c同时用作a和b时,a在f的主体内被修改,这违反了a是常量的假设,即使没有显式调用const_cast。
我已经尽可能地简化了这个示例,但是很容易想到不那么明显的用例(例如const方法作用于非常数引用参数)。
我的问题是:
- 我们真的能说上面的代码是常量正确的吗?
- 上述用例是已知模式吗?这是否被视为不良做法?
- 以上代码除了让读者摸不着头脑,还能成为技术问题的根源吗?例如未定义的行为,或编译器执行错误的简化假设?