1.namespace的用法
7点内容:
#include <iostream>
#include "game1.h"
#include "game2.h"
// 1.resolve name conflicts
void test01()
{
LOL::goAttack();//game1.h
KingGlory::goAttack();//game2.h
}
//2. you can put variables, functions, structures, classes in namespace.
namespace A{
int m_A;
void func();
struct Person{};
class Animal{};
}
void test02()
{
// 3.namespace must be declared under the global scope.
// namespace definition is not allowed in local fields.
#if 0
namespace B{
int m_B;
}
#endif
}
//4. namespace can be nested within namespace
namespace B{
int m_A = 10;
namespace C{
int m_A = 20;
}
}
void test03()
{
std::cout << "B_m_A = " << B::m_A << std::endl;
std::cout << "C_m_A = " << B::C::m_A << std::endl;
}
// 5.namespace is open,and content can be added at any time.
namespace B
{
int m_B = 100;
} // namespace B
void test04()
{
std::cout << "B_m_A = " << B::m_A << std::endl;
std::cout << "B_m_B = " << B::m_B << std::endl;
}
// 6.namespace can be anonymous
namespace{
// Equivalent to static
int m_C = 333;//static m_C
int m_D = 444;//static m_D
}
void test05()
{
std::cout << "m_C = " <<m_C <<std::endl;
std::cout << "m_D = " << ::m_D << std::endl;
}
//7. namespaces can have aliases.
namespace LongName{
int m_E = 10000;
}
void test06()
{
namespace ShortName = LongName;
std::cout << "namespace aliases:" << std::endl;
std::cout << "ShortName::m_E::" <<ShortName::m_E << std::endl;
}
int main()
{
test01();
test03();
test04();
test05();
test06();
return EXIT_SU***ESS;
}
2.using声明和using编译指令可以使用在全局,此时全局展开!!!
2.1.using的全局编译指令
#include <iostream>
namespace KingGlory{
int m_a;
class attack{
int m_b;
int m_c;
public:
void display()
{
std::cout << "call KingGlory::display \n";
}
};
void func()
{
std::cout << "call KingGlory::func\n";
}
namespace Tank{
int m_m_a;
void func()
{
std::cout << "call KingGlory::Tank::func\n";
}
}
}
using namespace KingGlory;//这里在全局作用域下声明,将会全局展开
void test01()
{
KingGlory::attack atk;
atk.display();
KingGlory::func();
KingGlory::Tank::func();
}
void test02()
{
func();//由于进行了KingGlory的全局展开,可以直接调用
}
void test03()
{
}
void test04()
{
}
void test05()
{
}
int main()
{
test01();
test02();
test03();
test04();
test05();
return EXIT_SU***ESS;
}
2.2using的全局声明
#include <iostream>
namespace KingGlory{
int m_a;
class attack{
int m_b;
int m_c;
public:
void display()
{
std::cout << "call KingGlory::display \n";
}
};
void func()
{
std::cout << "call KingGlory::func\n";
}
namespace Tank{
int m_m_a;
void func()
{
std::cout << "call KingGlory::Tank::func\n";
}
}
}
using KingGlory::func;
using KingGlory::m_a;
void test01()
{
func();
m_a = 100;
}
void test02()
{
}
void test03()
{
}
void test04()
{
}
void test05()
{
}
int main()
{
test01();
test02();
test03();
test04();
test05();
return EXIT_SU***ESS;
}
3.namespace的内存分配
一、namespace 中的类
- 类声明只是告诉编译器这个类型的“蓝图”,它不分配内存。
- 只有你在代码中实例化(定义)了这个类的对象,才会分配内存(在栈上或堆上,取决于如何实例化)。
- namespace 只是一个作用域管理工具,为类型和变量提供命名空间,方便区分不同模块的符号。
举例:
KingGlory::attack atk; // 这里才实例化对象,分配内存
这时程序会为 atk 分配内存。
二、namespace 中的基本类型变量
namespace KingGlory {
int m_a;
}
- 这是变量的定义,而非仅仅声明,是一个对象,所以会在程序的数据区静态分配内存(全局变量存储区)。
- 变量的内存布局由编译器在编译阶段安排,属于静态存储期,程序启动时就分配了内存。
- 不论你是否访问这个变量,内存都会被分配(除非优化器去掉未使用变量)。
举例:
std::cout << KingGlory::m_a << std::endl;
这行代码直接访问了变量。
三、命名空间中的变量是模板吗?
- 变量不是模板,它是具体的存储对象。
- 只有模板(template)才是蓝图,变量是具体实例。
- namespace 变量直接是静态存储对象。
四、变量内存分配时机
- 全局变量(如 namespace 变量)在程序开始时分配内存,属于静态存储期。
- 不会等到第一次访问才分配。
- 这和函数内的局部变量不同,局部变量是在运行时进入作用域时分配在栈上。
五、namespace 中的 const 和引用变量
namespace KingGlory {
const int m_c = 100;
const int& m_r = m_c;
}
-
const 变量默认具有内部链接(internal linkage),除非加
extern。 - 编译器通常会将 const 变量当做常量直接内联(常量折叠),不会单独分配内存(如果其地址未被取)。
- 但如果取地址或引用,则会分配内存。
- 引用本身不是对象,不占用内存,引用是某个对象的别名。
- 在上例中,
m_r是对m_c的引用,不单独分配内存,只是m_c的别名。
六、举例说明
namespace KingGlory {
int m_a = 10; // 一定分配内存(静态区)
const int m_c = 100; // 可能不分配内存,直接内联
const int& m_r = m_c; // 引用,不分配内存
static int m_s = 20; // 静态变量,分配内存,仅限本文件内访问
extern int m_ext; // 声明,未定义不分配内存
void func() {
std::cout << "func\n";
}
}
// 定义 extern 变量
int KingGlory::m_ext = 50;
-
m_a和m_s会分配内存。 -
m_c可能不分配内存,如果没取地址,直接作为编译时常量使用。 -
m_r是引用,不占用内存。 -
m_ext定义在外部,需要分配内存。
七、总结
| 类型 | 是否分配内存 | 分配时机 | 备注 |
|---|---|---|---|
| namespace 中声明的类(类型) | 不分配 | 无(类仅模板) | 只有实例化才分配内存 |
| namespace 中的基本类型变量 | 分配 | 编译期,程序启动时 | 静态存储区 |
| namespace 中的 const 变量 | 可能不分配(常量折叠) | 取地址时分配 | 默认内部链接,编译时优化 |
| namespace 中的 const 引用 | 不分配 | 无 | 引用是别名,不占用内存 |
| namespace 中的函数 | 不分配对象内存 | 无 | 代码区,函数体只存在一份 |
八、示例运行说明
void test01() {
KingGlory::attack atk; // 实例化,分配内存
atk.display();
KingGlory::func(); // 调用函数,无对象内存概念
KingGlory::Tank::func(); // 嵌套命名空间函数调用
}
-
atk是对象,分配内存。 - 函数调用不涉及变量内存,只是执行代码。
- 变量
KingGlory::m_a已经在程序启动时分配内存,无需首次调用时分配。