🔷 第二章 C++语言基础
📄 一句话概括

程序里名字会撞车:标准库有个 cout,你同事的代码里可能也有个叫 cout 的东西;两个库都提供一个叫 sort 的函数怎么办?命名空间(namespace)就是给名字加"姓氏"——std::cout 里的 std 就是"标准库这个家族"的门牌。本章写法 using namespace std; 的意思是"把 std 家族的门拆了,以后不用报姓氏",图省事;而正式项目里更推荐写全 std::cout。

一、为什么要有命名空间:一个真实会发生的问题

假设你和同事各写了一个函数:

// 你写的
void print() { cout << "我的 print"; }

// 同事写的(在另一个文件里)
void print() { cout << "他的 print"; }

两段代码各自都对,但放在同一个程序里就炸了——编译器看到 print() 不知道该叫谁。这叫名字冲突(name collision)。

程序越大、用的库越多,冲突机会越大。C++ 的解决办法不是"让大家都起长名字",而是允许重名,但要求你说明"哪个家族的":

A班::张伟     // 一个班里的张伟
B班::张伟     // 另一个班里的张伟——互不干扰

两个 :: 读作"作用域限定符",意思就是"去哪个范围里找这个名字"。

二、std 是什么

std = stdandard(标准)。C++ 标准库所有的名字都装在这个"大抽屉"里:

你写的 全名 是什么
cout std::cout 标准输出流对象
cin std::cin 标准输入流对象
endl std::endl 换行符
string std::string 字符串类型(第 6 章之后)
vector std::vector 动态数组(第 10 章之后)

所以 cout 只是"小名",它的全名是 std::cout。

三、三种写法,各有取舍

写法一:全部打开(教材与入门常用)

#include <iostream>
using namespace std;      // 从此这个文件里,std 里的名字都可以省姓氏

int main() {
    cout << "hi" << endl;  // 直接写小名
}

写法二:每次写全名(最稳)

#include <iostream>

int main() {
    std::cout << "hi" << std::endl;   // 每次都报门牌
}

写法三:只放行常用的几个(折中,进阶推荐)

#include <iostream>
using std::cout;
using std::endl;

int main() {
    cout << "hi" << endl;    // 只 cout/endl 可以省姓氏
}
📝 该用哪种?

现在:跟着教材写 using namespace std;,把注意力放在语法上。 以后(写多文件工程、用第三方库时):改成写法二或三。这不是"对错"问题,是"省事 vs 安全"的取舍。

四、自己定义命名空间(认识一下就好)

命名空间不是标准库的专利,你自己也能造:

#include <iostream>
using namespace std;

namespace mylib {                 // 开一个自己的"抽屉"
    void hello() {
        cout << "我是 mylib 里的 hello" << endl;
    }
}

int main() {
    mylib::hello();               // 用的时候报上"抽屉名"
    return 0;
}

看到什么算成功:屏幕输出"我是 mylib 里的 hello"。 这个能力什么时候真用:等你写自己的函数库、或者两个模块都想要同名函数的时候(第 9 章之后)。

五、动手 Demo:亲手制造一次"撞车"

  1. 新建 ns.cpp,照抄上面「写法一」的版本,编译通过
  2. 把 using namespace std; 注释掉,Ctrl+S → F11
  3. 预期:报错类似 'cout' was not declared in this scope
  4. 改法:要么加回 using,要么把 cout 改成 std::cout——两条路都能通,这就是上面说的取舍
  5. 再加一个实验:在 main 里定义 int cout = 5;,保留 using namespace std;
  6. 预期:报错说 cout 含义不明确(ambiguous)或重定义——亲自体验一次"名字打架"

看到什么算成功:三次都能看懂报错,并知道该往哪个方向修。

30 秒实验:在 main() 内部写 using namespace std;(而不是文件顶部),程序照样能编过——说明 using 也是讲作用域的:写在花括号里,只在那个花括号内有效。

六、常见误区

  1. "using namespace std; 是必须写的"——不是必须,是图省事。不写就要写 std::cout,程序一样正确
  2. "写了 using namespace std; 之后,我的变量名就安全了"——恰恰相反,它把 std 的门拆了,冲突风险变大(比如你定义一个叫 count 的变量,就可能和 std::count 打架)
  3. ":: 和 . 是一回事"——不是。:: 是作用域(哪个家族),. 是成员访问(哪个对象的哪个部分),第 8 章讲类时会正式区分
  4. "名字空间会让程序变慢"——不会。它纯粹是编译期的名字管理,跟运行速度无关
自测三问(点开对答案) 1. 命名空间要解决什么问题?——**名字冲突**:多个库或多人代码里出现同名函数/变量时,用 `名字空间::名字` 区分。 2. `cout` 的全名是什么?`std` 什么意思?——`std::cout`;`std` 是 standard(标准)的缩写,是标准库的名字空间。 3. `using namespace std;` 的利与弊?——利:写 `cout` 省事;弊:把 std 全部名字引入本文件,冲突风险变大。大项目建议写全名或只 `using` 常用项。

相关笔记