变量隐藏Accidental Variable Shadowing
6.5 — Variable shadowing (name hiding) | Learn C++ https://www.learncpp.com/cpp-tutorial/variable-shadowing-name-hiding/
Go的50度灰:Golang新开发者要注意的陷阱和常见错误 | 鸟窝 https://colobu.com/2015/09/07/gotchas-and-common-mistakes-in-go-golang/
6.5 — Variable shadowing (name hiding)
Each block defines its own scope region. So what happens when we have a variable inside a nested block that has the same name as a variable in an outer block? When this happens, the nested variable “hides” the outer variable in areas where they are both in scope. This is called name hiding or shadowing.
Shadowing of local variables
#include <iostream> int main()
{ // outer block
int apples { 5 }; // here's the outer block apples { // nested block
// apples refers to outer block apples here
std::cout << apples << '\n'; // print value of outer block apples int apples{ 0 }; // define apples in the scope of the nested block // apples now refers to the nested block apples
// the outer block apples is temporarily hidden apples = 10; // this assigns value 10 to nested block apples, not outer block apples std::cout << apples << '\n'; // print value of nested block apples
} // nested block apples destroyed std::cout << apples << '\n'; // prints value of outer block apples return 0;
} // outer block apples destroyed
If you run this program, it prints:
5
10
5
In the above program, we first declare a variable named apples in the outer block. This variable is visible within the inner block, which we can see by printing its value (5). Then we declare a different variable (also named apples) in the nested block. From this point to the end of the block, the name apples refers to the nested block apples, not the outer block apples.
Thus, when we assign value 10 to apples, we’re assigning it to the nested block apples. After printing this value (10), nested block apples is destroyed. The existence and value of outer block apples is not affected, and we prove this by printing the value of outer block apples (5).
Note that if the nested block apples had not been defined, the name apples in the nested block would still refer to the outer block apples, so the assignment of value 10 to apples would have applied to the outer block apples:
#include <iostream> int main()
{ // outer block
int apples{5}; // here's the outer block apples { // nested block
// apples refers to outer block apples here
std::cout << apples << '\n'; // print value of outer block apples // no inner block apples defined in this example apples = 10; // this applies to outer block apples std::cout << apples << '\n'; // print value of outer block apples
} // outer block apples retains its value even after we leave the nested block std::cout << apples << '\n'; // prints value of outer block apples return 0;
} // outer block apples destroyed
The above program prints:
5
10
10
When inside the nested block, there’s no way to directly access the shadowed variable from the outer block.
Shadowing of global variables
Similar to how variables in a nested block can shadow variables in an outer block, local variables with the same name as a global variable will shadow the global variable wherever the local variable is in scope:
#include <iostream>
int value { 5 }; // global variable void foo()
{
std::cout << "global variable value: " << value << '\n'; // value is not shadowed here, so this refers to the global value
} int main()
{
int value { 7 }; // hides the global variable value until the end of this block ++value; // increments local value, not global value std::cout << "local variable value: " << value << '\n'; foo(); return 0;
} // local value is destroyed
This code prints:
local variable value: 8
global variable value: 5
However, because global variables are part of the global namespace, we can use the scope operator (::) with no prefix to tell the compiler we mean the global variable instead of the local variable.
#include <iostream>
int value { 5 }; // global variable int main()
{
int value { 7 }; // hides the global variable value
++value; // increments local value, not global value --(::value); // decrements global value, not local value (parenthesis added for readability) std::cout << "local variable value: " << value << '\n';
std::cout << "global variable value: " << ::value << '\n'; return 0;
} // local value is destroyed
This code prints:
local variable value: 8
global variable value: 4
Avoid variable shadowing
Shadowing of local variables should generally be avoided, as it can lead to inadvertent errors where the wrong variable is used or modified. Some compilers will issue a warning when a variable is shadowed.
For the same reason that we recommend avoiding shadowing local variables, we recommend avoiding shadowing global variables as well. This is trivially avoidable if all of your global names use a “g_” prefix.
Best practice
Avoid variable shadowing.
Go的50度灰:Golang新开发者要注意的陷阱和常见错误 | 鸟窝 https://colobu.com/2015/09/07/gotchas-and-common-mistakes-in-go-golang/
然的变量隐藏Accidental Variable Shadowing
短式变量声明的语法如此的方便(尤其对于那些使用过动态语言的开发者而言),很容易让人把它当成一个正常的分配操作。如果你在一个新的代码块中犯了这个错误,将不会出现编译错误,但你的应用将不会做你所期望的事情。
package main
import "fmt"
func main() {
x := 1
fmt.Println(x) //prints 1
{
fmt.Println(x) //prints 1
x := 2
fmt.Println(x) //prints 2
}
fmt.Println(x) //prints 1 (bad if you need 2)
}
即使对于经验丰富的Go开发者而言,这也是一个非常常见的陷阱。这个坑很容易挖,但又很难发现。
你可以使用 vet命令来发现一些这样的问题。 默认情况下, vet不会执行这样的检查,你需要设置-shadow参数:go tool vet -shadow your_file.go。
变量隐藏Accidental Variable Shadowing的更多相关文章
- Codeforces Gym 100513M M. Variable Shadowing 暴力
M. Variable Shadowing Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100513/ ...
- R如何检验类别变量(nominal variable)与其他变量之间的相关性
1.使用Pearson积差相关系性进行检验的话可以判断两个变量之间的相关性是否显著以及相关性的强度 显著性检验 (significant test) 连续变量 vs 类别变量 (continuous ...
- Go语言规格说明书 之 变量声明(Variable/Short variable declarations)
go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,完整的介绍Go语 ...
- c++并发编程之条件变量(Condition Variable)
条件变量(Condition Variable)的一般用法是:线程 A 等待某个条件并挂起,直到线程 B 设置了这个条件,并通知条件变量,然后线程 A 被唤醒.经典的「生产者-消费者」问题就可以用条件 ...
- tensorflow变量作用域(variable scope)
举例说明 TensorFlow中的变量一般就是模型的参数.当模型复杂的时候共享变量会无比复杂. 官网给了一个case,当创建两层卷积的过滤器时,每输入一次图片就会创建一次过滤器对应的变量,但是我们希望 ...
- Oracle 变量 之 define variable declare 用法及区别
Oracle 变量 之 define variable declare 用法及区别 Table of Contents 1. 扯蛋 2. define和accept 3. variable 3.1. ...
- CMake语法—缓存变量(Cache Variable)
目录 CMake语法-缓存变量(Cache Variable) 1 CMake缓存变量 2 定义缓存变量 2.1 定义格式 2.2 定义示例代码 2.3 运行结果 2.4 小结 3 CMakeCach ...
- CMake语法—环境变量(Environment Variable)
目录 CMake语法-环境变量(Environment Variable) 1 定义环境变量 2 应用环境变量 2.1 代码结构 2.2 示例代码 2.3 运行结果 3 小结 CMake语法-环境变量 ...
- 引人瞩目的 CSS 变量(CSS Variable)
这是一个令人激动的革新. CSS 变量,顾名思义,也就是由网页的作者或用户定义的实体,用来指定文档中的特定变量. 更准确的说法,应该称之为 CSS 自定义属性 ,不过下文为了好理解都称之为 CSS 变 ...
随机推荐
- 前端技术VUE 的前世今生从PC 走向移动
一.Vue的前世 Vue 框架诞生于2014年,他的作者为中国人–尤雨溪(江苏无锡人).Vue用于构建交互式的Web界面的库,是一个构建数据驱动的Web界面渐进式框架,该框架遵循CMD规范,并且提供的 ...
- 一个简单的java项目使用hibernate连接mysql数据库
实体类与表对应文件Customer.hbm.xml <?xml version="1.0" encoding="UTF-8"?><!DOCTY ...
- Redis主从复制getshell技巧
Redis未授权漏洞常见的漏洞利用方式: Windows下,绝对路径写webshell .写入启动项. Linux下,绝对路径写webshell .公私钥认证获取root权限 .利用contrab计划 ...
- Redis中的常用命令哪些?
a.hset 存储一个哈希键值对的集合 b.hget获取一个哈希键的值c.hdel 删除一个或多个字段 d.hgetall 获取一个哈希是键值对的集合 e.lpush key value向链表左侧添加 ...
- 当Thymeleaf遇到向js中传值的操作
在使用Thymeleaf的时候.关于一些点击操作非常头疼.往往需要向JS里面传递各种东西. 然而,在用Thymeleaf的时候.js操作需要拼接语句.但是又不好拼接. 关于一些操作,一般也是在表格中. ...
- Beta冲刺——汇总随笔
一.代码规范与计划随笔 Beta冲刺--代码规范与计划 二.凡事预则立随笔 Beta冲刺--凡事预则立 三.10篇冲刺随笔 Beta冲刺--第一天 Beta冲刺--第二天 Beta冲刺--第三天 Be ...
- [Skill] git下载助手
缘由 某些时候需要下载git项目中的某个独立的文件或者文件夹下的内容,克隆全部速度过于慢 搜索下发现有开源的实现,特此记录下 方案 国内不便于fq 源码 服务地址 国外原作者 源码 服务地址 使用方法 ...
- Spark推荐系统实践
推荐系统是根据用户的行为.兴趣等特征,将用户感兴趣的信息.产品等推荐给用户的系统,它的出现主要是为了解决信息过载和用户无明确需求的问题,根据划分标准的不同,又分很多种类别: 根据目标用户的不同,可划分 ...
- Windows下如何玩转火热的go-zero
作者:阿啄debugIT 前言 go-zero 是一个集成了各种工程实践的 web 和 rpc 框架.通过弹性设计保障了大并发服务端的稳定性,经受了充分的实战检验. go-zero 包含极简的 API ...
- 【C++】《C++ Primer 》第七章
第七章 类 一.定义抽象数据类型 类背后的基本思想:数据抽象(data abstraction)和封装(encapsulation). 数据抽象是一种依赖于接口(interface)和实现(imple ...