int a=1,b=2;
int sum(constint& a, constint& b){
return(a+b);
}
int main(){
return sum(a,b);
}
//-------------------------------------------------int a=1,b=2;
int sum(int& a, int& b){
++a; ++b;
return(a+b);
}
int main(){
return sum(a,b);
}
#property strictstruct S1 { };
struct S2 { int val; };
template <typename T>
void f(T &t) {
struct SS: public T {
int f(int val) { return val; }
} ss = {0}; // Переменная типа SS
}
voidOnStart() {
S1 s1; f(s1);
S2 s2; f(s2);
}
在编译时将会弹出一个关于隐藏名字的警告。
'3.mq4'3.mq4 11struct has no members, size assigned to 1byte3.mq4 38struct has no members, size assigned to 1byte3.mq4 810
declaration of 'val' hides member declaration at line 43.mq4 9150 error(s), 3 warning(s) 14
...
对这个例子的测试。
...
我认为这些信息也是绝对无用的。我不是一个专业的程序员,但µl中的这种胡言乱语让我感到压力。我想知道如果对a和b的引用是恒定的,PVS Studio会不会产生一个警告(自己没有办法检查)?
不过,先弄清楚警告的内容,然后引用它作为论据,也不是一件坏事。PVS Studio会警告你,不是因为全局变量 被隐藏了,而是因为a和b是通过非常量引用传递的,但没有被修改。在这种情况下,他们认为a和b应该由一个常数引用来传递。例如,下面的例子并没有让这个分析器抱怨。
我很清楚PVS在责备我们什么。
再一次,我们没有编译数十亿行旧C/C++代码的责任负担。这取决于他们自己的编译器,不要因为产生警告而破坏了他们的业务。另一方面,我们对我们的应用语言的安全和错误控制负有责任,它与金钱打交道。
只有百分之几的MQL4/5代码作者是专业(真正意义上的)程序员。剩下的都是自学成才,根本不知道自己写的代码有多糟糕。
例如,在迁移到更新的MQL4之后,我们不得不手动翻阅kodobase中的数千个来源,并修复其旧代码中数量惊人的错误。即使不运行程序,编译器也已经发现并显示了很多错误。
这就是为什么我们不应该提出发布警告的主张,而是要修复自己的代码。
我很清楚PVS在责备我们什么。
再一次,我们没有编译数十亿行旧C/C++代码的责任负担。这取决于他们自己的编译器,不要因为产生警告而破坏了他们的业务。另一方面,我们对我们的应用语言的安全和错误控制负有责任,它与金钱打交道。
只有百分之几的MQL4/5代码作者是专业(真正意义上的)程序员。剩下的都是自学成才,根本不知道自己写的代码有多糟糕。
例如,在迁移到更新的MQL4之后,我们不得不手动翻阅kodobase中的数千个来源,并修复其旧代码中数量惊人的错误。即使不运行程序,编译器也已经发现并显示了很多错误。
这就是为什么你不应该抱怨发出警告,而应该修复你的代码。
如果数组允许你错过它的范围,那么在编写指标本身时,如果花费与编写指标相当的努力,而只是为了计算开始,那就非常愚蠢了。
你不必去挖掘这些代码,其中一半的代码没有被修复,而是被破坏了。你可以只做一个额外的属性来区分老的mql4,新的mql4或者新的mql4与strict。旧的编译器采取什么尺寸?我不知道,但可能不到一兆字节,在千兆字节的时代,拖着它走是没有问题的。但在这里,我们有一种英雄的行为--破坏代码库。
* * *
警告
声明'a'隐藏了第X行的全局声明
这是一个愚蠢的警告。如果在 "更高 "的世界里有人有问题,并不意味着其他人也可能有这样的问题。变量 是有范围 的,别人叫什么变量是私人问题。
如果允许一个数组滑过它的范围,那么在编写指标时,做出与编写指标本身相当的努力是非常愚蠢的,而只是为了计算出计算的起点。
你可以不挖这个代码,有一半的代码不是固定的而是坏的。可能只是做了一个额外的属性来区分老的mql4,新的或新的有严格的。旧的编译器采取什么尺寸?我不知道,但可能不到一兆字节,在千兆字节的时代,拖着它到处走没有问题。但这里做了一种英雄式的工作--破坏代码库。
确切地说,是修好了,没有坏。
如果一个错误是在编辑后溜进去的,那是完全有可能的--任何编辑都不可避免地会出现这样的错误。但这并不意味着你可以把单一的错误挂在旗子上,爬上纠正后的山头。
'a'隐藏了第X行的全局声明
这是一个愚蠢的警告。如果 "更高 "的世界中有人有问题,并不意味着其他人也可能有这样的问题。有一个变量可见的区域,任何人称之为变量都是一个私人问题。
潜在的错误就是潜在的错误,因为它根本就不一定是一个错误。
我不知道,我不知道。我们过去有一个经验法则,把4级或5级的认股权证放出来,并勾选把认股权证算作错误。
我们用pragmas摆脱了非常愚蠢的警告,但我们还是摆脱了它们。
这句话毫无意义,原则上没有给程序员提供任何有用的信息,因为并没有像声称的那样,对变量 "a "进行隐藏。
如果程序员故意使用隐藏,那么是的,这句话毫无意义,不能提供任何有用的信息。另一方面,如果隐瞒是由于疏忽而意外完成的,那么该备注可以让我们在早期阶段发现错误。
只有在创建变量的本地副本时才会发生隐藏,这也是一个完全合法的行为。即使因为这种隐藏而在代码中突然出现错误,也很容易被发现,正是因为搜索立即找到了相同的名字。如果我们开始改变和改动函数模板中的名称,这是编译器逻辑对这一规则的 "解决方案",那么错误搜索的情况将变得更加复杂,在理解代码方面的混乱将比比皆是。这似乎很明显。
局部变量 和参数都在一个作用域中,所以参数是否有这个名字或局部变量并不重要,但在任何情况下这个名字都会在外部作用域中隐藏一个名字。
隐藏与变量的副本没有关系,它与实体名称有关。是的,尽管它与类型等实体名称有关。
它的编译。
$ icpc -c 1.cpp $
还有这个。
它没有。
因为函数里面的名字A不再是一个类型名,而是一个变量参数名。在外层作用域中声明的类型的名称现在被变量-参数的名称所隐藏。你可以通过发现这段代码来间接窥见这一点
编译得很好。
$ icpc -c 1.cpp $
在MQL4++中,在通过变量-参数名称隐藏类型名称的阶段,即即使是空的函数体,这也不会被编译。
结果。
我不知道为什么,但我一点都不惊讶。
另一方面,对于C++来说,这样的代码是没有问题的。
编译尝试的结果。
$ icpc -c 1.cpp $
这个例子表明,隐藏与实体名称有关,与其他东西无关。
如果这句话不能切换,我们就得发明各种东西,比如异化。但如果它是可转动的,如英特尔编译器,你就不会有这样的问题。
MQL4++的问题不在于编译器功能本身,即检测嵌套作用域中的隐藏名称,而在于这个功能的基本不可操作性。
因此,人们不应该对警告提出主张,而应该修复自己的代码。
对所讨论的警告/注解的抱怨,我认为可以是一个--关于它们原则上的不可排除性。
当然,你也不能告诉程序员在语言中该做什么,不该做什么。
这样的信息(隐藏全局变量)在C++中就是没有意义的(mql被声明为像C++,对吗?)例如,这就是原因。
这样的信息(隐藏全局变量)在C++中就是没有意义的(mql被声明为像C++,对吗?)例如,这就是原因。
这里采取C++,是因为MQL4++没有结构/类模板--只有函数模板?
我不确定开发者是否意识到这一点,但类模板在MQL4++中也是可行的,尽管有很大的限制。特别是,这个例子可以通过以下方式移植到MQL4++中(在一个方法中也使用了一个参数而不是一个局部变量)。
在编译时将会弹出一个关于隐藏名字的警告。
如果OnStart()的最后一行被注释掉,关于隐藏名字的警告就会消失。
这里采用C++,是因为MQL4++中没有结构/类模板--只有函数模板?
...
一般来说,是的,但你也可以使用µl。