4

在 C# CLR 中学习 C++ 之了解 namespace

 2 years ago
source link: https://www.cnblogs.com/huangxincheng/p/16646061.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在 C# CLR 中学习 C++ 之了解 namespace

相信大家在分析 dump 时,经常会看到 WKSSRV 这样的字眼,如下代码所示:


00007ffa`778a07b8 coreclr!WKS::gc_heap::segment_standby_list = 0x00000000`00000000
00007ffa`778a3870 coreclr!WKS::qpf = 0x989680
00007ffa`7789da30 coreclr!SVR::heap_select::numa_node_to_heap_map = unsigned short [1028]
00007ffa`7789f2d0 coreclr!SVR::gc_heap::should_expand_in_full_gc = 0n0

其实这就是命名空间,即 coreclr 在编译源码的时候,为 WKSSVR 各编译了一份,不知道这么做的初衷是什么,这里就不管了,接下来看下 coreclr 中大概长啥样子。


namespace WKS {
    #include "gcimpl.h"
    #include "gc.cpp"
}

namespace SVR {
    #include "gcimpl.h"
    #include "gc.cpp"
}

二:聊一聊 namespace

其实和 C# 的 namespace 本质差不多,都是起到隔离的作用,而且和 using 的配合使用和 C# 也是如出一辙,太有意思了。

1. 简单的隔离

在 C++ 中默认只有一个 namespace,所以相同的变量会出现冲突,解决办法就是用 namespace 隔离,参考如下代码:


namespace WKS
{
	int a = 10;
	int b = 11;
}

namespace SRV {

	int a = 100;
	int b = 101;
}

int main()
{
	printf("WKS::a= %d \n", WKS::a);
	printf("SRV::a= %d \n", SRV::a);
}

214741-20220901120041141-1921607060.png

当然还可以嵌套使用,比如改成这样。


namespace WKS
{
	namespace V1 {
		int a = 10;
		int b = 11;
	}
}

int main()
{
	printf("WKS::a= %d \n", WKS::V1::a);
}

接下来看下汇编代码:

214741-20220901120041150-361797272.png

哈哈,看到上面的 WKS::V1::a 感觉是不是挺舒服的,也特能理解目前的 coreclr!WKS::xxx 了, 不过这里有一个麻烦的地方,就是每次用 a 的时候都要输入很长的前缀,那有没有简化的方法呢? 当然有啦。

2. 使用 using 导入

接下来我们用 using 直接在 main 函数中定义字段,后续就不需要再写长长的前缀引用了,参考代码如下:


namespace WKS
{
	namespace V1 {
		int a = 10;
		int b = 11;
	}
}

int main()
{
	using WKS::V1::a;

	printf("WKS::V1::a1= %d \n", a);
}

214741-20220901120041139-27964637.png

3. 使用 using 定义别名

定义别名这功能特别好,个人感觉已经完全替代以前的 typedef 功能,比如下面的代码是完全一样的。


int main()
{
	typedef const char* PCHAR;

	using PCHAR2 = const char*;

	PCHAR ptr1 = "hello world1";

	PCHAR2 ptr2 = "hello world2";
}

如果还不信的话,可以看下它们各自生成的汇编代码。


	PCHAR ptr1 = "hello world1";
00007FF79856183B  lea         rax,[string "hello world1" (07FF798569C10h)]  
00007FF798561842  mov         qword ptr [ptr1],rax  

	PCHAR2 ptr2 = "hello world2";
00007FF798561846  lea         rax,[string "hello world2" (07FF798569CE8h)]  
00007FF79856184D  mov         qword ptr [ptr2],rax  

4. 使用 using namespace 导入

这个是最普遍的,我们对系统库的调用,无一不是用 using namespace 方式的,比如下面的代码。


using namespace std;

int main()
{
	string str = "hello world";
}

接下来我们把 V1 导入到 main 方法中,这样就可以自由自在的使用 WKS::V1 中的内容了,参考如下代码:


namespace WKS
{
	namespace V1 {
		int a = 10;
		int b = 11;
	}
}

int main()
{
	using namespace WKS::V1;

	printf("a=%d, b=%d", a, b);
}

214741-20220901120041126-1742204366.png

好了,这就是对 namespace 的一点理解,本篇就说这么多吧,希望对你有帮助。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK