如何检测常量参数的中间函数值变化



我在一些代码中遇到了一个严重的错误。这是简化版本:

#include <iostream>
class A
{
public:
std::string s;

void run(const std::string& x)
{
// do some "read-only" stuff with "x"
std::cout << "x = " << x << std::endl;
// Since I passed X as a const referece, I expected string never to change
// but actually, it does get changed by clear() function
clear();
// trying to do something else with "x", 
// but now it has a different value although I declared it as 
// "const". This killed the code logic.
std::cout << "x = " << x << std::endl;
// is there some way to detect possible change of X here during compile-time?
}

void clear()
{
// in my actual code, this doesn't even happen here, but 3 levels deep on some other code that gets called
s.clear();
}
};
int main()
{
A a;
a.s = "test";
a.run(a.s);

return 0;
}

基本上,调用.run((的代码过去用于所有类型的字符串,在某一点上,我需要对象"的确切值;a.s";有,所以我只是把a.s放在那里,然后过了一段时间,我注意到程序的行为很奇怪。我追踪到了这个。

现在,我明白为什么会发生这种情况,但它看起来是一个非常难以追踪和检测的错误。您可以看到声明为const&它的价值突然发生了变化。

有什么方法可以在编译时检测到这一点吗?我正在使用CLang和MSVC。

谢谢。

在编译时有什么方法可以检测到这一点吗?

我不这么认为。修改由const引用引用的成员变量并没有本质上的错误,所以编译器没有理由对此发出警告。编译器无法读懂你的想法来了解你的期望。

在某些用法中,这种错误的假设可能会导致明确的错误,例如未定义的行为,如果被识别,则可以进行诊断。我怀疑在一般情况下识别这种情况在计算上会相当昂贵,所以我不会依赖它


重新设计接口可能会使这种情况变得不可能。例如:

struct wrapper {
std::string str;
};

void run(const wrapper& x);

x.str不会对该成员进行别名,因为该成员不在wrapper内部。

最新更新