跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ 入门:发展历史、命名空间与输入输出详解

C++ 基于 C 语言扩展,支持面向对象。本文梳理了 C++ 的发展脉络与版本迭代,列举了服务器、游戏引擎等核心应用场景及经典学习书籍。重点解析了命名空间的定义、嵌套及多文件合并机制,解决标识符冲突问题。同时对比了 C 风格 IO 与 C++ 流式 IO(cin/cout),介绍了流同步优化技巧,帮助初学者平滑过渡。

山野诗人发布于 2026/3/28更新于 2026/10/2286 浏览
C++ 入门:发展历史、命名空间与输入输出详解

C++ 的发展历史

1. 发展历史

起源(1979-1983): C++ 的起源可以追溯到 1979 年,当时 Bjarne Stroustrup 在贝尔实验室从事计算机科学和软件工程的研究工作。面对项目中复杂的软件开发任务,特别是模拟和操作系统的开发工作,他感受到了现有语言(如 C 语言)在表达能力、可维护性和可扩展性方面的不足。1983 年,Bjarne Stroustrup 在 C 语言的基础上添加了面向对象编程的特性,设计出了 C++ 语言的雏形,此时的 C++ 已经有了类、封装、继承等核心概念,为后来的面向对象编程奠定了基础。这一年该语言被正式命名为 C++。

标准化(1989-1994): C++ 的标准化工作于 1989 年开始,并成立了一个 ANSI 和 ISO(International Standards Organization)国际标准化组织的联合标准化委员会。1994 年标准化委员会提出了第一个标准化草案。在该草案中,委员会在保持斯特劳斯特卢普最初定义的所有特征的同时,还增加了部分新特征。

在完成 C++ 标准化的第一个草案后不久,STL(Standard Template Library)是惠普实验室开发的一系列软件的统称。它是由 Alexander Stepanov、Meng Lee 和 David R Musser 在惠普实验室工作时所开发出来的。在通过了标准化第一个草案之后,联合标准化委员会投票并通过了将 STL 包含到 C++ 标准中的提议。STL 对 C++ 的扩展超出 C++ 的最初定义范围。虽然在标准中增加 STL 是个很重要的决定,但也因此延缓了 C++ 标准化的进程。

正式投入使用(1997): 1997 年 11 月 14 日,联合标准化委员会通过了该标准的最终草案。1998 年,C++ 的 ANSI/ISO 标准被投入使用。

C++ 的诞生是为了弥补 C 语言的不足之处!所以部分的 C 语言依然能够在 C++ 程序中成功运行~

2. C++ 的版本更新

C++ 的版本更新基本上在 5 年左右更新一次,大家可以参考下图来了解 C++ 的历代版本与更新内容:

文章配图 文章配图

3. C++ 的参考文档

  • Reference - C++ Reference
  • C++ reference - cppreference.com

说明:第一个链接不是 C++ 官方文档,标准也只更新到 C++11,但是以头文件形式呈现,内容比较易看好懂。后两个链接分别是 C++ 官方文档的英文版,信息很全,更新到了最新的 C++ 标准,但是相比第一个不那么易看;这两个文档各有优势,我们结合着使用。

C++ 的学习建议

1. C++ 的应用领域

C++ 的应用领域非常广泛,包括服务器端、游戏(引擎)、机器学习引擎、音视频处理、嵌入式软件、电信设备、金融应用、基础库、操作系统、编译器、基础架构、基础工具、硬件交互等很多方面。

  • 大型系统软件开发:如编译器、数据库、操作系统、浏览器等等。
  • 音视频处理:常见的音视频开源库和方案有 FFmpeg、WebRTC、Mediasoup、ijkplayer,音视频开发最主要的技术栈就是 C++。
  • PC 客户端开发:一般是开发 Windows 上的桌面软件,比如 WPS 之类的,技术栈的话一般是 C++ 和 QT,QT 是一个跨平台的 C++ 图形用户界面(GUI)程序。
  • :各种大型应用网络连接的高并发后台服务。这块 Java 也比较多,C++ 主要用于一些对性能要求比较高的地方。如:游戏服务、流媒体服务、量化高频交易服务等。
服务端开发
  • 游戏引擎开发:很多游戏引擎就都是使用 C++ 开发的,游戏开发要掌握 C++ 基础和数据结构,学习图形学知识,掌握游戏引擎和框架,了解引擎实现,引擎源代码可以学习 UE4、Cocos2d-x 等开源引擎实现。
  • 嵌入式开发:嵌入式把具有计算能力的主控板嵌入到机器装置或者电子装置的内部,通过软件能够控制这些装置。比如:智能手环、摄像头、扫地机器人、智能音响、门禁系统、车载系统等等,粗略一点,嵌入式开发主要分为嵌入式应用和嵌入式驱动开发。
  • 机器学习引擎:机器学习底层的很多算法都是用 C++ 实现的,上层用 python 封装起来。如果你只想准备数据训练模型,那么学会 Python 基本上就够了,如果你想做机器学习系统的开发,那么需要学会 C++。
  • 测试开发 / 测试:每个公司研发团队,有研发就有测试,测试主要分为测试开发和功能测试,测试开发一般是使用一些测试工具 (selenium、Jmeter 等),设计测试用例,然后写一些脚本进行自动化测试,性能测试等,有些还需要自行开发一些测试用具。功能测试主要是根据产品的功能,设计测试用例,然后手动的方式进行测试。
  • 2. 学习书籍推荐

    文章配图

    • C++ Primer:主要讲解语法,经典的语法书籍,前后中期都可以看,前期如果自学看可能会有点晦涩难懂,能看懂多少看懂多少,中后期作为语法字典,非常好用。
    • STL 源码剖析:主要从底层实现的角度结合 STL 源码,庖丁解牛式剖析 STL 的实现,是侯捷老师的经典之作。可以很好的帮助我们学习别人用语法是如何实现出高效简洁的数据结构和算法代码,如何使用泛型封装等。让我们不再坐井观天,闭门造车,本书课程上一半以后,中后期可以看。
    • Effective C++:这本书也是侯捷老师翻译的,本书有的⼀句评价,把 C++ 程序员分为看过此书的和没看过此书的。本书主要讲了 55 个如何正确高效使用 C++ 的条款,建议中后期可以看一遍,工作 1-2 年后再看一遍,相信会有不一样的收获。

    C++ 的第一个程序

    C++ 兼容 C 语言绝大多数的语法,所以 C 语言实现的 hello world 依旧可以运行,C++ 中需要把定义文件代码后缀改为.cpp,vs 编译器看到是.cpp 就会调用 C++ 编译器编译,linux 下要用 g++ 编译,不再是 gcc。

    // 这里使用的是 test.cpp
    #include<stdio.h>
    int main() {
        printf("Hello World\n");
        return 0;
    }
    

    然而 C++ 有自己的一套输入输出设备,所以在 C++ 中的 hello world 应该是这样:

    #include<iostream>
    using namespace std;
    int main() {
        cout << "hello world\n" << endl;
        return 0;
    }
    

    命名空间

    1. namespace 的价值

    在 C/C++ 中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace 关键字的出现就是针对这种问题的。

    C 语言项目类似下面程序这样的命名冲突是普遍存在的问题,C++ 引入 namespace 就是为了更好的解决这样的问题。

    // 命名冲突
    #include<stdio.h>
    #include<stdlib.h>
    int rand = 10;
    int main() {
        // 编译报错:error C2365: 'rand': 重定义;以前的定义是'函数'
        printf("%d", rand);
        return 0;
    }
    

    报错如图:

    文章配图

    因为库函数 stdlib.h 中已经定义了 rand,所以 C 语言就无法运行这串代码了。但在 C++ 的输入输出中就可以用 namespace 来解决这个问题。

    2. namespace 的定义

    • 定义命名空间,需要使用到 namespace 关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
    • namespace 本质是定义出一个域,这个域跟全局域各自独立,不同的域可以定义同名变量,所以下面的 rand 不在冲突了。
    • C++ 中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找一个变量/函数/类型出处 (声明或定义) 的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。
    • namespace 只能定义在全局,当然他还可以嵌套定义。
    • 项目工程中多文件中定义的同名 namespace 会认为是⼀个 namespace,不会冲突。
    • C++ 标准库都放在⼀个叫 std(standard) 的命名空间中。
    1)使用 namespace 来命名空间,以及使用命名空间
    #include<stdio.h>
    #include<stdlib.h>
    namespace A //A 是命名空间的名字,一般开发中是用项目名字做命名空间名
    {
        // 命名空间中可以定义变量/函数/类型
        int rand = 10;
        int ADD(int a,int b) {
            return a + b;
        }
        struct Node {
            struct Node* next;
            int val;
        };
    }//注意这里没有分号!!
    int a = 1;
    int main() {
        //编译器语法查找确认规则是默认先局部查找->全局查找->没有找到就报未声明的标识符这个错误
        //::域作用限定符,这里指定作用域,就直接按这个域去找->没有找到就报未声明的标识符这个错误
        int a = 0;
        printf("%d\n", a);
        printf("%d\n", ::a);//::前面不加域就是默认全局域!不会到命名空间里查找!
        printf("%p\n", rand);//这里的 rand 是 stdlib.h 中的指针,要用%p 访问
        printf("%d\n", A::rand);//这里访问的就是 A 域中的 rand
        printf("%p\n", A::ADD);
        printf("%d\n", A::ADD(1, 2));//这里是直接调用该函数
        //A::struct Node node;//这是错误的
        struct A::Node node;
        return 0;
    }
    

    这个程序的运行结果如下:

    文章配图

    !!!这里需要注意的是命名空间域不会影响变量的生命周期(是一个全局的生命周期)。

    2)命名空间的嵌套使用
    #include<stdio.h>
    #include<stdlib.h>
    //命名空间的嵌套使用
    namespace A {
        namespace a {
            int rand = 10;
            int ADD(int a,int b) {
                return a + b;
            }
        }
        namespace b {
            int rand = 20;
            int ADD(int a, int b) {
                return (a + b) * 10;
            }
        }
    }
    int main() {
        printf("%d\n", A::a::rand);
        printf("%d\n", A::b::rand);
        printf("%d\n", A::a::ADD(1, 2));
        printf("%d\n", A::b::ADD(1, 2));
        return 0;
    }
    

    程序的运行结果如下:

    文章配图

    命名空间的嵌套可以嵌套很多层,但是不推荐,因为那样写起来也很不方便~

    我们在项目中经常会用到命名空间的嵌套,大家可以看下面的图片来理解一下

    文章配图

    3)多文件定义的命名空间问题

    多文件中可以定义同名 namespace,他们会默认合并在一起,就像同一个 namespace 一样。下面给大家简单演示一下~

    test.cpp

    #include<stdio.h>
    #include<stdlib.h>
    #include"Stack.h"
    #include"Queue.h"
    int main() {
        st::stack s1;
        st::Init(&s1);
        st::Push(&s1, 1);
        st::Push(&s1, 2);
        st::Pop(&s1);
        queue::Queue q1;
        queue::Init(&q1);
        queue::Push(&q1, 1);
        queue::Push(&q1, 2);
        queue::Pop(&q1);
        return 0;
    }
    

    stack.h

    #pragma once
    #include<stdio.h>
    #include<stdlib.h>
    #include<assert.h>
    #include<stdbool.h>
    namespace st {
        typedef int STDataType;
        typedef struct stack {
            STDataType* arr;
            int top;
            int capacity;
        }stack;
        void Init(stack* ps);
        void Push(stack* ps, STDataType x);
        void Pop(stack* ps);
    }
    

    stack.cpp

    #include"Stack.h"
    namespace st {
        void Init(stack* ps) {
            //......
        }
        void Push(stack* ps, STDataType x) {
            //...
        }
        void Pop(stack* ps) {
            //...
        }
    }
    

    queue.h

    #pragma once
    #include<stdio.h>
    #include<stdlib.h>
    #include<assert.h>
    #include<stdbool.h>
    namespace queue {
        typedef int QDataType;
        typedef struct QueueNode {
            QDataType data;
            struct QueueNode* next;
        }QueueNode;
        typedef struct Queue {
            QueueNode* phead;
            QueueNode* ptail;
        }Queue;
        void Init(Queue* pq);
        void Push(Queue* pq, QDataType x);
        void Pop(Queue* pq);
    }
    

    queue.cpp

    #include"Queue.h"
    namespace queue {
        void Init(Queue* pq) {
            //......
        }
        void Push(Queue* pq, QDataType x) {
            //...
        }
        void Pop(Queue* pq) {
            //...
        }
    }
    

    3. namespace 命名空间的使用

    编译查找一个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以下面程序会编译报错。所以我们要使用命名空间中定义的变量/函数,有三种方式:

    • 指定命名空间访问,项目中推荐这种方式。
    • using 将命名空间中某个成员展开,项目中经常访问的不存在冲突的成员推荐这种方式。
    • 展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。
    1)指定命名空间访问
    #include<iostream>//C++ 中不需要带.h
    #include<algorithm>
    int main() {
        int a[5] = { 4,1,2,5 };
        // 指定命名空间访问
        std::sort(a, a + 4);
        return 0;
    }
    
    2)using 将命名空间中某个成员展开
    #include<iostream>
    #include<algorithm>
    //命名空间中成员部分展开
    using std::cout;
    using std::cin;
    int main() {
        int a, b;
        cin >> a >> b;//输入
        cout << a << " " << b << '\n';//输出
        return 0;
    }
    

    在这里我们可以看到部分展开了之后 cout 就不需要在前面加东西了,但是 cin 前面还是需要加 std 的。这个展开方式还是推荐在大型项目中使用的~

    3)展开命名空间中全部成员
    #include<iostream>
    #include<algorithm>
    //命名空间中成员全部展开
    using namespace std;
    int main() {
        int a, b;
        cin >> a >> b;//输入
        cout << a << " " << b << '\n';//输出
        return 0;
    }
    

    这里就是把 std 中的所有成员全部展开,在做算法题或者小程序没有命名冲突的情况下可以使用,而且使用起来比较方便,但是在大型项目中就不推荐使用了~

    C++ 输入&输出

    • 是 Input Output Stream 的缩写,是标准的输入、输出流库,定义了标准的输入、输出对象。
    • std::cin 是 istream 类的对象,它主要面向窄字符(narrow characters (of type char))的标准输入流。
    • std::cout 是 ostream 类的对象,它主要面向窄字符的标准输出流。
    • std::endl 是一个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区。
    • << 是流插入运算符, >> 是流提取运算符。(C 语言还用这两个运算符做位运算左移 / 右移)
    • 使用 C++ 输入输出更方便,不需要像 printf/scanf 输入输出时那样,需要手动指定格式,C++ 的输入输出可以自动识别变量类型 (本质是通过函数重载实现的,这个以后会讲到),其实最重要的是 C++ 的流能更好的支持自定义类型对象的输入输出。
    • IO 流涉及类和对象,运算符重载、继承等很多面向对象的知识,这些知识我们还没有讲解,所以这里我们只能简单认识一下 C++ IO 流的用法,后面我们会有专门的一个章节来细节 IO 流库。
    • cout/cin/endl 等都属于 C++ 标准库,C++ 标准库都放在一个叫 std (standard) 的命名空间中,所以要通过命名空间的使用方式去用他们。
    • 一般日常练习中我们可以 using namespace std,实际项目开发中不建议 using namespace std。
    • 这里我们没有包含 <stdio.h>,也可以使用 printf 和 scanf,在包含间接包含了。vs 系列编译器是这样的,其他编译器可能会报错。

    举例说明:

    #include<iostream>
    int main() {
        int i = 100;
        double b = 1.11000;
        //任何变量都会转换成字符串,插入到流中
        //cout 会自动识别
        std::cout << i << "\n";
        std::cout << b << "\n";
        std::cout << "hello world" << std::endl;//end line
        std::cout << "hello" << " " << "world" << std::endl;
        std::cin >> i >> b;//cin 是输入
        std::cout << i << " " << b << std::endl;//cout 是输出
        return 0;
    }
    

    换行用 '\n' 的效率会比使用 endl 更高,除此以外,cout 和 cin 的效率其实也是不如 printf 和 scanf 的,但是 printf 和 scanf 不能处理类(也就是更复杂的类型),而 C++ 的 IO 流支持复杂类型的输入输出。在 C++ 的 IO 流中我们可以通过取消同步流的操作来解决这个问题,代码如下:

    #include<iostream>
    using namespace std;
    int main() {
        // 在 io 需求比较高的地方,如部分大量输入的竞赛题中,加上以下 3 行代码
        // 可以提高 C++IO 效率
        ios_base::sync_with_stdio(false);
        cin.tie(nullptr);
        cout.tie(nullptr);
        return 0;
    }
    

    目录

    1. C++ 的发展历史
    2. 1. 发展历史
    3. 2. C++ 的版本更新
    4. 3. C++ 的参考文档
    5. C++ 的学习建议
    6. 1. C++ 的应用领域
    7. 2. 学习书籍推荐
    8. C++ 的第一个程序
    9. 命名空间
    10. 1. namespace 的价值
    11. 2. namespace 的定义
    12. 1)使用 namespace 来命名空间,以及使用命名空间
    13. 2)命名空间的嵌套使用
    14. 3)多文件定义的命名空间问题
    15. 3. namespace 命名空间的使用
    16. 1)指定命名空间访问
    17. 2)using 将命名空间中某个成员展开
    18. 3)展开命名空间中全部成员
    19. C++ 输入&输出

    更多推荐文章

    查看全部
    • Redis Hash 类型核心指令与实战详解
    • 2026 年 3 月全球 AI 前沿动态:模型、智能体与硬件突破
    • 医疗 NLP 实战:电子病历分析与疾病诊断辅助
    • 基于 FPGA 的 OV5640 摄像头视频采集与 VGA 显示设计
    • Dify 本地部署安装教程(Windows + Docker)
    • Flutter OpenHarmony 实战:通义万相 AIGC 联调与相册持久化
    • 无人机视觉语言导航入门:基本概念与定义
    • Flutter for OpenHarmony 实战:通义万相 AIGC 联调与相册持久化
    • AI 产品经理必备技能与实战指南
    • QLExpress Java 动态脚本引擎使用指南
    • Flutter webrtc_interface 鸿蒙化适配与实战指南
    • ABB 机器人虚拟示教器基础操作与核心设置
    • OpenClaw 浏览器自动化 4 种实现方式详解
    • Linux 进程通信:System V 共享内存原理与 C++ 封装实战
    • HTML5 页面 XSS 攻击的 AI 识别与防御策略
    • Stable Diffusion 零基础入门与实战指南
    • Obsidian Copilot API 密钥配置指南:OpenRouter、Gemini 与 OpenAI
    • 智谱发布 GLM-4-Plus 基座大模型及全模型家族
    • C++ 模板基础:泛型编程与函数类模板详解
    • 程序员身份认同与银行服务的定制化探索

    相关免费在线工具

    • 加密/解密文本

      使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

    • Gemini 图片去水印

      基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

    • Base64 字符串编码/解码

      将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

    • Base64 文件转换器

      将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

    • Markdown转HTML

      将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

    • HTML转Markdown

      将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online