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 namespacefunctionsclasses 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 一开始就初始化

属于 ifwhile 和 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. IE和火狐的css兼容性问题

     CSS对浏览器器的兼容性具有很高的价值,通常情况下IE和Firefox存在很大的解析差异,这里介绍一下兼容要点. 1.DOCTYPE 影响 CSS 处理 2.FF: div 设置 margin-le ...

  2. 这一次,真正掌握composer

      思维导图 composer是现代PHP的基石 现代高级编程语言,依赖管理工具是必不可少的.Java有Maven,Python有pip,Nodejs有npm, 而在composer出现之前,PHP只 ...

  3. SQL 创建表

    SQL 创建表是通过SQL CREATE TABLE 语句来实现,该语句是DDL SQL语句.CREATE TABLE语句用于创建用于存储数据的表.在创建表时,可以为列定义主键.惟一键和外键等完整性约 ...

  4. Memcache安装配置

    介绍 Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像.视频.文件以及数据库检索的结果等.简单的说就是将数据调 ...

  5. Mac配置虚拟环境Virtualenv,安装Python科学计算包详解

    参考: https://www.jianshu.com/p/51140800e8b4 安装 virtualenvwrapper Virtaulenvwrapper是virtualenv的扩展包,可以更 ...

  6. 一个好隐蔽的C/C++代码bug

    来自:微博@ruanyf, 一本书上说,下面的 C 语言代码可能会产生无限循环.看了半天,才意识到 Bug 在哪里. 完美解答: 数组下标越界.数组a总共有10个值,a[0]~a[9].for循环里面 ...

  7. RecursiveSequence(HDU-5950)【矩阵快速幂】

    题目链接: 题意:Si=S(i-1)+2*S(i-2)+i^4,求Sn. 思路:想到了矩阵快速幂,实在没想出来怎么构造矩阵.... 首先构造一个向量vec={a,b,16,8,4,2,1}. 在构造求 ...

  8. go变量的定义并赋值

    变量在定义时没有明确的初始化时会赋值为_零值_. 零值是: 数值类型为 `0`, 布尔类型为 `false`, 字符串为 `""`(空字符串). package main impo ...

  9. ASP.NET Core分布式项目-2.oauth密码模式identity server4实现

    源码下载 这里根据<ASP.NET Core分布式项目-1.IdentityServer4登录中心>的代码来继续更新oauth密码模式,这里的密码模式比上次的客户端模式更安全 在WebAp ...

  10. Ubuntu 搭建 配置 nfs服务器

    什么是NFS? NFS(Network File System)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源.在NFS的应用中,本地NF ...