C++ std 命名空间

在 C++ 中,**命名空间**是一组相关的名称或标识符(函数、类、变量)的集合,它有助于将这些标识符与来自其他命名空间或全局命名空间的类似标识符区分开来。

C++ 标准库的标识符定义在一个名为 std 的命名空间中。

为了使用任何属于标准库的标识符,我们需要指定它属于 std 命名空间。一种方法是使用作用域解析运算符 ::。例如,

std::cout << "Hello World!";

这里,我们在 cout 前使用了 std:: 代码。这告诉 C++ 编译器我们使用的 cout 对象属于 std 命名空间。


C++ std 标识符

<iostream><string><vector> 等标准头文件提供的所有标准库标识符都声明在 std 命名空间中。

例如,标识符 cincout 定义在 std 命名空间中 <iostream> 的标准头文件中。


利用 std 标识符

我们可以通过以下方式在程序中使用 std 命名空间的标识符:

  • :: 运算符
  • using 声明
  • using 指令

std Namespace Using :: Operator

我们访问 std 命名空间中标识符的第一种方式是直接用前缀 std:: 限定标识符。这里,

  • std 是 C++ 标准库命名空间
  • :: 是作用域解析运算符

例如,

#include <iostream>

int main() {

  std::string first_name;

  std::cout << "Enter your first name: ";
  std::cin >> first_name;
  std::cout << "Hello " << first_name << "!" << std::endl;
  std::cout << "Welcome!";

  return 0;
}

输出

Enter your first name: Marty
Hello Marty!
Welcome!

在上面的示例中,我们通过编写 std:: 来直接使用作用域解析运算符 ::std 命名空间访问标识符。

请注意,我们在 stringcincoutendl 前面加上了 std:: 前缀,写法如下:

  • std::string
  • std::cin
  • std::cout
  • std::endl

如果从上面的代码中删除 std:: 前缀,我们会收到一个错误。


std Namespace With using Declaration

我们可以借助 **using 声明** 将选定的标识符引入当前作用域。要做到这一点,我们使用 using 关键字。

这样做之后,我们就无需在指定的标识符前加上 std:: 前缀了。例如,

#include <iostream>

// using declartion for cout, endl and string using std::cout; using std::endl; using std::string;
int main() { string first_name ; cout << "Enter your first name: "; std::cin >> first_name; cout << "Hello " << first_name << "!" << endl; cout << "Welcome!"; return 0; }

输出

Enter your first name: Scarlet
Hello Scarlet!
Welcome!

在上面的示例中,我们使用了 using 声明来引入我们想从 std 命名空间使用的标识符。

using std::cout;
using std::endl;
using std::string;

在这里,我们告诉编译器,我们只想将 coutendlstring 这几个标识符从标准命名空间引入到当前作用域。

这使得我们不必在每次需要访问这些标识符时都显式添加 std:: 前缀。

请注意,我们在程序中使用了 std::cin 而不是 cin

std::cin >> first_name;

这是因为我们在 using 声明中没有包含 std::cin


std Namespace With using Directive

我们可以使用 **using 指令** 将 std 命名空间 **的所有标识符** 引入,就好像它们是全局声明的一样。要做到这一点,我们使用 using 关键字。

通过这样做,我们可以:

  • 避免使用 std:: 前缀
  • 避免反复使用 using 声明

例如,

#include <iostream>

// using directive using namespace std;
int main() { string first_name ; cout << "Enter your first name: "; cin >> first_name; cout << "Hello " << first_name << "!" << endl; cout << "Welcome!"; return 0; }

输出

Enter your first name: Jack
Hello Jack!
Welcome!

在上面的示例中,我们使用了 using **指令** 将 std 命名空间的所有标识符引入我们的程序,包括 stringcoutcinendl 标识符。

注意事项

  • **using 声明** 只将命名空间中指定的标识符引入当前作用域。
  • **using 指令** 将命名空间的所有标识符引入当前作用域。

不良实践:using namespace std

由于 using namespace stdstd 命名空间的所有标识符引入全局命名空间,这可能会与其他命名空间产生命名冲突。例如,除了 std 命名空间中的 cout 之外,可能还有其他具有 cout 名称的实体。

因此,如果我们同时使用那个其他命名空间(包含另一个 cout 实体)和 std 命名空间,那么编译器将不知道使用哪个 cout。结果是,每次使用 cout 时都会出现错误。

让我们来看一个例子,

#include <iostream>

using namespace std;
// function template for swapping numbers template <class T> void swap (T& a, T& b) { cout << "Before Swapping\na = " << a << " and b = " << b << endl; T temp = a; a = b; b = temp; cout << "After swapping\n"; cout << "a = " << a << " and " << b << " = " << b << endl; } int main() { int a = 1; int b = 2; swap(a, b); return 0; }

输出

error: call of overloaded 'swap(int&, int&)' is ambiguous

在上面的示例中,我们使用了一个 函数模板 创建了自己的 swap() 函数版本。然后我们尝试使用整数 a = 1b = 2 调用 swap() 函数,

swap(a, b);

swap() 函数接收两个整数并交换它们,同时显示交换前后 ab 的值。但是如果我们尝试运行代码,会收到一个错误。

为什么会收到错误?

这里,我们因为程序中的以下代码而收到错误:

using namespace std;

这是一个 **using 指令**,它将标准命名空间的所有标识符引入当前命名空间。但是 std 命名空间包含了它自己的 swap() 函数。

因此,编译器无法确定使用哪个版本的 swap():是 std::swap() 还是我们创建的自定义函数。

为了避免此错误,我们必须从程序中删除 using namespace std; 代码。


潜在的专业问题

假设你正在处理一个大型程序或项目。比如说,你正在使用一个名为 swapLib 的库,它实现了自己的 swap() 函数。

如果你使用了 using namespace std,它可能会像我们的示例一样产生歧义,即是使用 swapLib 库中的 swap() 还是标准命名空间中的 swap()

注意:如果你只使用标准库中的少量名称,最好使用 **using 声明** 来选择性地引入标识符。

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战