Scopes

Named entities, such as variables, functions, and compound types need to be declared before being used in C++. The point in the program where this declaration happens influences its visibility:

1. global scope:An entity declared outside any block has(meaning that its name is valid anywhere in the code)

2. block scope:While an entity declared within a block(such as a function or a selective statement, has, and is only visible within the specific block in which it is declared, but not outside it)

3. local variables:Variables with block scope are known as (variable declared in the body of a function is a local variable that extends until the end of the the function (i.e., until the brace } that closes the function definition),)

but not outside it:

 
int foo;        // global variable

int some_function () { int bar;      // local variable
bar = ; } int other_function () { foo = ; // ok: foo is a global variable
bar = ; // wrong: bar is not visible from this function
}

 

In each scope, a name can only represent one entity. For example, there cannot be two variables with the same name in the same scope:

1
2
3
4
5
6
7
int some_function () { int x; x = 0; double x; // wrong: name already used in this scope x = 0.0; }

The visibility of an entity with block scope extends until the end of the block, including inner blocks. Nevertheless, an inner block, because it is a different block, can re-utilize a name existing in an outer scope to refer to a different entity; in this case, the name will refer to a different entity only within the inner block, hiding the entity it names outside. While outside it, it will still refer to the original entity. For example:

 
// inner block scopes
#include <iostream>
using namespace std; int main () { int x = ; int y = ; { int x; // ok, inner scope.
x = ; // sets value to inner x
y = ; // sets value to (outer) y
cout << "inner block:\n"; cout << "x: " << x << '\n'; cout << "y: " << y << '\n'; } cout << "outer block:\n"; cout << "x: " << x << '\n'; cout << "y: " << y << '\n'; return ; }

 

inner block: x:  y:  outer block: x:  y: 

 

Note that y is not hidden in the inner block, and thus accessing y still accesses the outer variable.

Variables declared in declarations that introduce a block, such as function parameters and variables declared in loops and conditions (such as those declared on a for or an if) are local to the block they introduce.

Namespaces

Only one entity can exist with a particular name in a particular scope. This is seldom a problem for local names, since blocks tend to be relatively short, and names have particular purposes within them, such as naming a counter variable, an argument, etc...

But non-local names bring more possibilities for name collision, especially considering that libraries may declare many functions, types, and variables, neither of them local in nature, and some of them very generic.

Namespaces allow to group named entities that otherwise would have global scope into narrower scopes, giving themnamespace scope. This allows organizing the elements of programs into different logical scopes referred to by names.

The syntax to declare a namespaces is:

namespace identifier { named_entities }

 

Where identifier is any valid identifier and named_entities is the set of variables, types and functions that are included within the namespace. For example:

 

 
namespace myNamespace { int a, b; }

 

In this case, the variables a and b are normal variables declared within a namespace called myNamespace.

These variables can be accessed from within their namespace normally, with their identifier (either a or b), but if accessed from outside the myNamespace namespace they have to be properly qualified with the scope operator ::. For example, to access the previous variables from outside myNamespace they should be qualified like:

myNamespace::a myNamespace::b 

 

Namespaces are particularly useful to avoid name collisions. For example:

 
// namespaces
#include <iostream>
using namespace std; namespace foo // 这里使用了 namespace
{ int value() { return ; } } namespace bar // 这里使用了 namespace
{ const double pi = 3.1416; double value() { return *pi; } // 这里用的 return 2*pi } int main () { cout << foo::value() << '\n'; // 使用了::
cout << bar::value() << '\n'; // 使用了::
cout << bar::pi << '\n'; return ; }

 

6.2832
3.1416

 

In this case, there are two functions with the same name: value. One is defined within the namespace foo, and the other one in bar. No redefinition errors happen thanks to namespaces. Notice also how pi is accessed in an unqualified manner from within namespace bar (just as pi), while it is again accessed in main, but here it needs to be qualified as second::pi.

Namespaces can be split: Two segments of a code can be declared in the same namespace:

1
2
3
namespace foo { int a; } namespace bar { int b; } namespace foo { int c; }

This declares three variables: a and c are in namespace foo, while b is in namespace bar. Namespaces can even extend across different translation units (i.e., across different files of source code).

using

The keyword using introduces a name into the current declarative region (such as a block), thus avoiding the need to qualify the name. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// using
#include <iostream>
using namespace std; namespace first { int x = ; int y = ; } namespace second { double x = 3.1416; double y = 2.7183; } int main () { using first::x; using second::y; cout << x << '\n'; cout << y << '\n'; cout << first::y << '\n'; cout << second::x << '\n'; return ; }

 

2.7183

3.1416

 

Notice how in main, the variable x (without any name qualifier) refers to first::x, whereas y refers to second::y, just as specified by the using declarations. The variables first::y and second::x can still be accessed, but require fully qualified names.

The keyword using can also be used as a directive to introduce an entire namespace:

 
// using
#include <iostream>
using namespace std; namespace first { int x = ; int y = ; } namespace second { double x = 3.1416; double y = 2.7183; } int main () { using namespace first; cout << x << '\n'; cout << y << '\n'; cout << second::x << '\n'; cout << second::y << '\n'; return ; }

 


3.1416
2.7183

 

In this case, by declaring that we were using namespace first, all direct uses of x and y without name qualifiers were also looked up in namespace first.

using and using namespace have validity only in the same block in which they are stated or in the entire source code file if they are used directly in the global scope. For example, it would be possible to first use the objects of one namespace and then those of another one by splitting the code in different blocks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// using namespace example #include <iostream> using namespace std; namespace first { int x = 5; } namespace second { double x = 3.1416; } int main () { { using namespace first; cout << x << '\n'; } { using namespace second; cout << x << '\n'; } return 0; }
5 3.1416

Namespace aliasing

Existing namespaces can be aliased with new names, with the following syntax:

namespace new_name = current_name;

The std namespace

All the entities (variables, types, constants, and functions) of the standard C++ library are declared within the stdnamespace. Most examples in these tutorials, in fact, include the following line:

 
using namespace std;

This introduces direct visibility of all the names of the std namespace into the code. This is done in these tutorials to facilitate comprehension and shorten the length of the examples, but many programmers prefer to qualify each of the elements of the standard library used in their programs. For example, instead of:

 
cout << "Hello world!";

It is common to instead see:

 
std::cout << "Hello world!";

Whether the elements in the std namespace are introduced with using declarations or are fully qualified on every use does not change the behavior or efficiency of the resulting program in any way. It is mostly a matter of style preference, although for projects mixing libraries, explicit qualification tends to be preferred.

Storage classes

The storage for variables with global or namespace scope is allocated for the entire duration of the program. This is known as static storage, and it contrasts with the storage for local variables (those declared within a block). These use what is known as automatic storage. The storage for local variables is only available during the block in which they are declared; after that, that same storage may be used for a local variable of some other function, or used otherwise.

But there is another substantial difference between variables with static storage and variables with automatic storage:
- Variables with static storage (such as global variables) that are not explicitly initialized are automatically initialized to zeroes.
- Variables with automatic storage (such as local variables) that are not explicitly initialized are left uninitialized, and thus have an undetermined value.

For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
// static vs automatic storage #include <iostream> using namespace std; int x; int main () { int y; cout << x << '\n'; cout << y << '\n'; return 0; }
0 4285838

The actual output may vary, but only the value of x is guaranteed to be zero. y can actually contain just about any value

(转) Name visibility的更多相关文章

  1. HTML5 Page Visibility

    什么是 Page Visibility ? Page Visibility 即页面可见性,通过 visibilityState 的值检测页面当前是否可见.当一个网站是可见或点击选中的状态时 Page ...

  2. 关于display:none 和visibility:hidden 的区别

    1.占据空间 :none 隐藏后不占据空间 visibility占据空间 2.回流与渲染:none产生回流与渲染 ? 可以通过oprea中的Profiler 工具测试. 关于回流的详细介绍:http: ...

  3. Android笔记——Android中visibility属性VISIBLE、INVISIBLE、GONE的区别

    在Android开发中,大部分控件都有visibility这个属性,其属性有3个分别为"visible "."invisible"."gone&quo ...

  4. Android百度地图 关于visibility="gone"的奇葩问题

    最近在项目中遇到一个奇葩问题,花了很长时间,在这里记录下. 问题描述:我的主界面是ViewPager+Fragment,并且设置缓存了我的4个ViewPager页面.左侧是一个侧滑菜单,点击相应按钮打 ...

  5. css-display:none和visibility:hidden的不同

    摘自张鑫旭老师的博客-- display:none和visibility:hidden都能使元素隐藏,但是有明显区别,主要有以下三点: 空间占据 重排与重绘 株连性 1.空间占据. 使用display ...

  6. display:none与visibility:hidden区别

    display:none与visibility:hidden有一个共同的作用是隐藏要显示的内容isplay:none 隐藏,但是不占空间 “看不见摸不到” 加载 display:none 隐藏,但是不 ...

  7. Visibility属性控制元素的显示和隐藏

    w3cschool案例: <!DOCTYPE html> <html> <body> <p id="p1">这是一段文本.</ ...

  8. 页面可见生Page Visibility

    Page Visibility 会在浏览器的 document 对象上添加两个属性 hidden 和 visibilityState .如果当前的标签被激活了,那么 document.hidden 的 ...

  9. transition与visibility之间的小tips

    之前经常遇到这个问题,就是在用transition样式的时候经常不起作用,一个元素处于隐藏状态(display:none)时,通过添加一个class将元素显示出来,这样其实过度效果是不起作用的,懒做的 ...

  10. 深入理解CSS元素可见性visibility

    × 目录 [1]定义 [2]属性 [3]display[4]JS[5]transition [6]API[7]DEMO 前面的话 visibility属性常见于与display属性的比较中.但实际上, ...

随机推荐

  1. 用phpMyAdmin修改mysql数据库密码

    1初始数据库密码为空. 2第一步,点击phpMyAdmin里的用户选项. 3选择root localhost用户名,点击编辑权限. 4此时会出来修改权限的页面,里面可以设置的选项还是比较多的,暂时不管 ...

  2. 关于JDBC中Class.forName的疑惑

    一直以来都不知道为什么执行了 Class.forName(); 之后,通过DriverManager.getConnection(); 就可以获取相关数据库的连接Connection的实现呢?今天看了 ...

  3. 【Nutch2.3基础教程】集成Nutch/Hadoop/Hbase/Solr构建搜索引擎:安装及运行【集群环境】

    1.下载相关软件,并解压 版本号如下: (1)apache-nutch-2.3 (2) hadoop-1.2.1 (3)hbase-0.92.1 (4)solr-4.9.0 并解压至/opt/jedi ...

  4. Java根据字节数据判断文件类型

    通常,在WEB系统中,上传文件时都需要做文件的类型校验,大致有如下几种方法: 1. 通过后缀名,如exe,jpg,bmp,rar,zip等等. 2. 通过读取文件,获取文件的Content-type来 ...

  5. iOS基本的发短信和打电话调用

    电话.短信是手机的基础功能,iOS中提供了接口,让我们调用.这篇文章简单的介绍一下iOS的打电话.发短信在程序中怎么调用. 1.打电话 [[UIApplication sharedApplicatio ...

  6. Nginx 内置变量,细化规则,真实IP获取及限制连接请求

    希望下周测试之后能用起来!!!感觉很有用的. http://www.bzfshop.net/article/176.html http://www.cr173.com/html/19761_1.htm ...

  7. gridview列显示,截取其中前面的几个字显示出来,当鼠标放上去的时候显示全部——使用LinkButton的方法

    使用LinkButton的方法<asp:LinkButton ToolTip ='<%#Eval("FilePath") %>' runat="serv ...

  8. ulimit -c unlimited

    tomcat 产生core日志: app:/usr/local/apache-tomcat-7.0.55_8082/logs# ulimit -a core file size (blocks, -c ...

  9. Swing透明和变换

    以前或许大家对一个UI组件是否透明没有那么关心,但是自从Vista的毛玻璃出现后,UI透明就成了大家非常关注的一个话题,于是Java阵营开始了铺天盖地的讨论如何实现透明的效果,但是很不幸的是无论组件如 ...

  10. linux下C和shell调用的popen函数

    说明:      本文介绍popen函数的使用方法和行为机理,并给出实际的例子来辅助说明了popen函数的使用方法. popen函数使用FIFO管道执行外部程序,首先让我们看看popen的函数原型吧: ...