scope和namespace

scope就是我们常说的作用域,namespace是C++引入的一个关键字。这两种都和作用域有些微妙的联系,下面 引自Global scope vs global namespace的回答很好解释了这两个概念。

In C++, every name has its scope outside which it doesn't exist. A scope can be defined by many ways : it can be defined by namespace, functions, classes and just { }.

So a namespace, global or otherwise, defines a scope. The global namespace refers to using ::, and the symbols defined in this namespace are said to have global scope. A symbol, by default, exists in a global namespace, unless it is defined inside a block starts with keyword namespace, or it is a member of a class, or a local variable of a function:

int a; //this a is defined in global namespace
//which means, its scope is global. It exists everywhere. namespace N
{
int a; //it is defined in a non-global namespace called `N`
//outside N it doesn't exist.
}
void f()
{
int a; //its scope is the function itself.
//outside the function, a doesn't exist.
{
int a; //the curly braces defines this a's scope!
}
}
class A
{
int a; //its scope is the class itself.
//outside A, it doesn't exist.
};

Also note that a name can be hidden by inner scope defined by either namespace, function, or class. So the name a inside namespace N hides the name a in the global namspace. In the same way, the name in the function and class hides the name in the global namespace. If you face such situation, then you can use ::a to refer to the name defined in the global namespace:

int a = 10;

namespace N
{
int a = 100; void f()
{
int a = 1000;
std::cout << a << std::endl; //prints 1000
std::cout << N::a << std::endl; //prints 100
std::cout << ::a << std::endl; //prints 10
}
}

我们说的global scope用符号表示的话就是::,C++中具名namespace,可以说是把global scope进行了划分。除此之外class,function,{ }都是划分scope的方式。

关于namespace几点建议

在命名空间的最后注释出命名空间的名字。

// .h 文件
namespace mynamespace { // 所有声明都置于命名空间中
// 注意不要使用缩进
class MyClass {
public:
...
void Foo();
}; } // namespace mynamespace

不应该使用 using 指示 引入整个命名空间的标识符号。

// 禁止 —— 污染命名空间
using namespace foo;

头文件中不要使用namespace别名(如果在namespace内部使用可以),cc文件没有限制

// 在 .cc 中使用别名缩短常用的命名空间
namespace baz = ::foo::bar::baz;
// 在 .h 中使用别名缩短常用的命名空间
namespace librarian {
namespace impl { // 仅限内部使用
namespace sidetable = ::pipeline_diagnostics::sidetable;
} // namespace impl inline void my_inline_function() {
// 限制在一个函数中的命名空间别名
namespace baz = ::foo::bar::baz;
...
}
} // namespace librarian

禁止用inline namespace,inline namespace只在大型版本控制里有用。

匿名namespace和静态变量

在 .cc 文件中定义一个不需要被外部引用的变量时,可以将它们放在匿名命名空间或声明为 static 。但是不要在 .h 文件中使用匿名namespace,.h中可以使用static。匿名命名空间说白了就是文件作用域,就像 C static 声明的作用域一样,后者已经被 C++ 标准提倡弃用。匿名命名空间的声明和具名的格式相同,在最后注释上 namespace :

namespace {
...
} // namespace  

局部变量

C++ 允许在函数的任何位置声明变量. 我们提倡在尽可能小的作用域中声明变量, 离第一次使用越近越好. 这使得代码浏览者更容易定位变量声明的位置, 了解变量的类型和初始值. 特别是,应使用初始化的方式替代声明再赋值, 比如:

int i;
i = f(); // 坏——初始化和声明分离
int j = g(); // 好——初始化时声明
vector<int> v;
v.push_back(1); // 用花括号初始化更好
v.push_back(2);
vector<int> v = {1, 2}; // 好——v 一开始就初始化

属于 if, while 和 for 语句的变量应当在这些语句中正常地声明,这样子这些变量的作用域就被限制在这些语句中了,举例而言:  

while (const char* p = strchr(str, '/')) str = p + 1;

有一个例外, 如果变量是一个对象, 每次进入作用域都要调用其构造函数, 每次退出作用域都要调用其析构函数. 这会导致效率降低.

// 低效的实现
for (int i = 0; i < 1000000; ++i) {
Foo f; // 构造函数和析构函数分别调用 1000000 次!
f.DoSomething(i);
}

在循环作用域外面声明这类变量要高效的多:

Foo f;                      // 构造函数和析构函数只调用 1 次
for (int i = 0; i < 1000000; ++i) {
f.DoSomething(i);
}

  

C++——namespace的更多相关文章

  1. 理解Docker(3):Docker 使用 Linux namespace 隔离容器的运行环境

    本系列文章将介绍Docker的有关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

  2. C++ namespace

    namespace, 命名空间, 用于解决命名冲突的问题. Python中的package/module, Javascript中的object, Java中的package都具有这样的功能. 如何使 ...

  3. C++ 之namespace常见用法

    一.背景 需要使用Visual studio的C++,此篇对namespace的常用用法做个记录. 二.正文 namespace通常用来给类或者函数做个区间定义,以使编译器能准确定位到适合的类或者函数 ...

  4. using namespace std 和 using std::cin

    相较using std::cin使用using namespace std不会使得程序的效率变低,或者稳定性降低,只是这样作会将很多的名字引入程序,使得程序员使用的名字集合变小,容易引起命名冲突. 在 ...

  5. Why Namespace? - 每天5分钟玩转 OpenStack(102)

    上一节我们讨论了 Neutron 将虚拟 router 放置到 namespace 中实现了不同 subnet 之间的路由.今天探讨为什么要用 namespace 封装 router? 回顾一下前面的 ...

  6. struts2中错误There is no Action mapped for namespace [/] and action name [] associated with context path

    1 There is no Action mapped for namespace [/] and action name [] associated with context path [/Stru ...

  7. PHP 命名空间(namespace)

    PHP 命名空间(namespace) PHP 命名空间(namespace)是在PHP 5.3中加入的,如果你学过C#和Java,那命名空间就不算什么新事物. 不过在PHP当中还是有着相当重要的意义 ...

  8. AMD and CMD are dead之Why Namespace?

    缘由 当我看到_Franky兄的微博的时候: 我觉得我有必要出来详细说说KMDjs到底有什么本质上的优势了,连教主_Franky.貘吃馍香都不能理解他的好处,那么可想而知,在前端圈.或是全端圈.或是I ...

  9. 使用mvc时,在视图view中使用强类型视图,在web.config文件中添加命名空间namespace的引用不起作用,解决方法

    这是view中的model代码: @model t_user_info 这是web.config配置文件只的代码: <namespaces> <add namespace=" ...

  10. C、C++: 引用、指针、实例、内存模型、namespace

    // HelloWorld.cpp : Defines the entry point for the console application. // #include "stdafx.h& ...

随机推荐

  1. NodeJs本地搭建服务器,模拟接口请求,获取json数据

    最近在学习Node.js,虽然就感觉学了点皮毛,感觉这个语言还不错,并且也会一步步慢慢的学着的,这里实现下NodeJs本地搭建服务器,模拟接口请求,获取json数据. 具体的使用我就不写了,这个博客写 ...

  2. MySQL中创建存储过程示例

    在这个示例中需要用到一张名为test_table的表,我们使用show create table test_table查看表的创建过程: CREATE TABLE `test_table` ( `id ...

  3. Vue-cli中的安装方法

    vue-cli脚手架模板是基于node下的npm来完成安装的所以首先需要安装node 1.安装node,vue运行需要基于npm一定的版本,所以首先升级npm到最新的版本,而在安装的过程中个人比较喜欢 ...

  4. 机器学习第一章——NFL的个人理解

    第一篇博客,想给自己的学习加深记忆.看到书中第一个公式时,本来想直接看证明结果就好,然鹅...作者在备注上写:这里只用到一些非常基础的数学知识,只准备读第一章且有“数学恐惧”的读者可跳过...嘤嘤嘤, ...

  5. Dapper操作Sql Server和MySql数据库

    1. 在配置文件web.config中添加连接字符串 <connectionStrings> <add name="sqlconnectionString" co ...

  6. UiPath工具取得网页上面的数据,写入到csv,Outlook邮件发送

    问题描述: 想取得网页上面的股票价格,之后写入到csv文本里面之后添加附件发送邮件. 解决方法: 利用UIPath工具来取得数据,之后写入再发送. 具体步骤: 1.打开网页,之后找到所显示的股票行情的 ...

  7. [转帖]分享Oracle的四道经典面试题,值得收藏

    分享Oracle的四道经典面试题,值得收藏 原创 波波说运维 2019-07-20 00:02:00 https://www.toutiao.com/i6713901660919300621/ 概述 ...

  8. 路由器02---PandoraBox配置

    1.安装libc 什么是libc,这里贴一个gnu官方的解释 Any Unix-like operating system needs a C library: the library which d ...

  9. SrpingBoot入门到入坟04-配置文件

    SpringBoot使用一个全局的配置文件,名称是固定,作用就是修改SpringBoot自动配置的默认值. *application.properties *application.yml 先看看两者 ...

  10. 20191011-构建我们公司自己的自动化接口测试框架-Action的request方法封装

    Action模块 封装接口request方法,根据传入的参数调用不同的请求方法,因为项目特色,我们公司的接口都是get和post方法,所以仅仅封装了get和post方法: import request ...