C++的标准化于1989年开始,当时成立了一个ANSI和ISO国际标准化组织的联合标准化委员会。1994年标准化委员会提出了C++标准化的第一个草案。不久,惠普实验室开发了一系列软件,统称为STL(Standard Template Library),联合标准化委员会投票通过了将STL包含在C++标准的提议。但STL对C++的扩展超出了C++最初定义标准范围,虽然在标准中加入STL是个重要的决定,但也因此延缓了C++的标准化进程。 直到1997年11月14日,联合标准化委员会通过了该标准的最终草案。1998年,C++的ANSI/ISO标准被投入使用。

而每隔几年,C++都会迎来一次版本更新,如1998年的C++98、2003年的C++03、2011年的C++11、2014年的C++14……目前2026年的C++26正在制定中。

一句话总结:C++是一门扩展了C语言的语言,它兼容C语言的大部分语法

2. C++参考文档

https://legacy.cplusplus.com/reference https://en.cppreference.com/w/ https://zh.cppreference.com/w/cpp 这三个网站是C++程序设计者最常用的C++参考文档。

第一个我们已经不陌生了,在C语言学习阶段经常去查询库函数:

在这里插入图片描述

在这里插入图片描述

然而它并不是C++的官方文档,是“民间大神”建设的科普性网站。在UI和用户访问方面相比官方文档改进了不少。缺点是它太久没有更新,内容很老甚至可能不是正确的了。

第二个网站就是C++的官方文档,是全英文的,也是最推荐大家学习的。第三个网站是官方文档的翻译版。我们鼓励大家还是阅读官方文档,因为作为程序员培养英文文档阅读能力还是很重要的,有一些知识与技术可能并没有汉化,要依靠自己去查询学习。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

二、namespace命名空间

1. C语言的一个缺陷

还记得我们讲过:作用域是一个程序设计概念。通常来说,针对每一个变量,都有它的可用的范围,这就是作用域。C语言中我们只接触到了全局域、局部域,而在同一个域中不能出现相同名字的变量或函数或类型,否则会编译报错。在大型的项目中,可能要用到成千上万个函数,团队多人协作时经常会有起名冲突的问题,这是C语言无法解决的问题。

2. namespace

所以,C++克服了这一问题,提出了命名空间这一概念。定义命名空间,需要用关键字namespace,后面加自定义空间名字,接上一对{ },{ }中即为命名空间的成员,可以定义变量、函数、类型。

tip:进入C++的学习,记得创建源文件后缀是 .cpp 哦

代码语言:javascript

AI代码解释

namespace test //test是自定义名字
{
    int a = 1;
    void Swap(int* x, int* y)
    {
        *x = *x ^ *y;
        *y = *x ^ *y;
        *x = *x ^ *y;
    }
    struct st
    {
      int n;
      char m;
    };
}

namespace的本质是定义了一个域,和其他局部域、全局域相互独立。既然它们是不同的域,完全可以在各自其中定义相同名字的变量或函数或结构了。举个例子:

代码语言:javascript

AI代码解释

#include"test.h"
int a = 2;
int main()
{
    return 0;
}
//如果test.h中有:int a;则程序会报错
//如果test.h中有:namespace test{ int a; }不会报错
//前者程序中的全局域中出现了两次定义a(头文件中一次主函数上面一次),
//后者的全局域和命名空间域各只出现了一次定义a

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

C++中域有全局域、函数局部域、命名空间域、类域。域影响的是编译时语法查找一个变量或函数或类型出处的逻辑,所以在一个域内出现的相同名字会使语法无法判断。有了域隔离,名字冲突就解决了。除此之外,局部域和全局域还会影响变量的生命周期,而命名空间域和类域的变量生命周期默认是整个程序的生命周期。

我们还要知道的是:

  • namespace只能定义在全局,不能定义在函数里。
  • namespace可以嵌套定义。
  • 项目工程中多文件中定义的同名namespace会被认为是一个namespace,会被程序自动合并,不会冲突。
  • C++标准库都放在一个叫std(standard)的命名空间中。

代码语言:javascript

AI代码解释

//namespace的嵌套定义
namespace MiHoYo
{
    int a = 10;
    char c = 'Q';

	namespace Honkai_3
	{
		int a = 1;
		char c = 'X';
	}

	namespace Genshen_Impact
	{
		int a = 4;
		char c = 'J';
	}

	namespace Honkai_Star_Rail
	{
		int a = 9;
		char c = 'O';
	}
}
3. 命名空间的使用
3.1 命名空间成员访问

访问命名空间的操作符是::,使用方式和结构体的. ->很像。 比如,语句test::a,是从命名空间test中找变量a;::a默认是从全局域中找变量a;而a就是先从局部域找a,找不到再从全局域找a。函数或类型也同理 代码示例:

代码语言:javascript

AI代码解释

#include<stdio.h>

namespace test1
{
	int a = 1;
	namespace test2
	{
		int a = 2;
	}
}

int a = 3;

int main()
{
	int a = 4;
	
	printf("%d\n", test1::a); //访问test1的a
	printf("%d\n", test1::test2::a); //访问test1中的test2中的a
	printf("%d\n", ::a); //默认访问全局域的a
	printf("%d\n", a); //访问局部域的a,局部域没有a则访问全局域的a

	return 0;
}

在这里插入图片描述

在这里插入图片描述

函数也是一样的:

代码语言:javascript

AI代码解释

#include<stdio.h>

namespace test
{
	int a = 2;
	int b = 8;

	int Add(int x, int y)
	{
		return x + y;
	}
}

int main()
{
	printf("%d", test::Add(test::a, test::b));
	return 0;
}

在这里插入图片描述

在这里插入图片描述

3.2 using展开

C++中还有一个关键字using,能将命名空间成员展开,即让这个成员从命名空间中“出来”到全局域中,相当于全局域中再定义了一次,原命名空间仍保留成员。使用方法是using 命名空间名::成员名;,如:

代码语言:javascript

AI代码解释

namespace test
{
    int a = 1;
    char c = 'P';
}
using test::a; //这一句可以看做int a = 1;
void main()
{
    printf("%d ", a);
    printf("%d ", test::a);
    //两者结果相同
}

在这里插入图片描述

在这里插入图片描述但是,展开了a相当于还是在全局域中定义了a,又带来了命名冲突的风险。所以只有项目中经常访问不存在冲突的成员推荐这种方式。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐