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

C++ 初阶:命名空间、输入输出、缺省参数与函数重载

C++ 基础语法详解,涵盖命名空间解决冲突机制、标准输入输出流用法、缺省参数规则及函数重载原理。深入解析引用与指针的区别、内联函数优化策略以及 nullptr 空指针的规范使用。通过代码示例演示常见错误点与最佳实践,适合初学者系统掌握 C++ 核心概念。

人间失格发布于 2026/3/27更新于 2026/9/750 浏览
C++ 初阶:命名空间、输入输出、缺省参数与函数重载

一、namespace

1.1 namespace 的引入

在 C/C++ 中,变量、函数和类的名称都存在于全局作用域中,极易产生冲突。使用命名空间的目的是对标识符进行本地化,避免名字污染。

C 语言中的冲突示例:

#include <stdio.h>
#include <stdlib.h>

int rand = 6;

int main() {
    printf("%d", rand);
}

上述代码中,自定义的 rand 可能与标准库冲突。C++ 引入 namespace 正是为了解决这一问题。

C++ 优化方案:

#include <stdio.h>

namespace m {
    int rand = 6;
}

int main() {
    printf("%d", m::rand);
}

1.2 namespace 的定义

定义命名空间需使用 namespace 关键字,后跟名字及一对花括号。命名空间中可定义变量、函数或类型。

namespace m {
    int a = 6;
    int Add(int a, int b) {
        return a + b;
    }
    struct Node {
        struct Node* next;
        int val;
    };
}
  • 本质:定义出一个独立的域,与全局域隔离。不同域可定义同名变量。
  • 域的影响:影响编译时语法查找逻辑(声明或定义出处)。局部域和全局域还影响生命周期,而命名空间域和类域不影响。
  • 嵌套:支持嵌套定义。
  • namespace m {
        namespace n {
            int a = 0;
            int b = 9;
        }
        int c = 6;
    }
    
    • 多文件:工程中多个文件中定义的同名 namespace 会被视为同一个 namespace,不会冲突。
    • 标准库:C++ 标准库通常放在 std (standard) 命名空间中。

    1.3 namespace 使用

    默认查找只在局部或全局进行,访问命名空间成员有三种方式:

    1. 指定命名空间访问(推荐):
    std::cout
    
    1. using 展开特定成员(无冲突时推荐):
    using m::a;
    
    1. 展开全部成员(小练习可用,项目慎用):
    using namespace std;
    

    二、输入输出

    #include <iostream>
    
    int main() {
        int a = 0;
        double b = 0;
        std::cin >> a >> b;
        std::cout << a << " " << b << std::endl;
        return 0;
    }
    
    • IO Stream:Input Output Stream 缩写,是标准的输入输出流库。
    • 对象:std::cin 是 istream 类对象,面向窄字符输入;std::cout 是 ostream 类对象,面向窄字符输出。
    • 操作符:<< 是流插入运算符,>> 是流提取运算符。
    • 优势:自动识别变量类型,无需像 printf/scanf 那样手动指定格式。
    • 性能优化:在 IO 需求高的场景(如竞赛),建议关闭同步以提升速度:
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    

    三、缺省参数

    缺省参数指声明或定义时为形参指定默认值。调用时若未传实参则用默认值,否则用实参。分为全缺省和半缺省。

    #include <iostream>
    using namespace std;
    
    int Add(int a = 1, int b = 2) {
        return a + b;
    }
    
    int main() {
        cout << Add(4, 3) << endl; // 输出 7
        cout << Add() << endl;     // 输出 3
        return 0;
    }
    
    • 规则:半缺省必须从右往左连续缺省,不能跳跃。调用时必须从左往右依次传参。
    • 分离声明定义:缺省参数只能出现在函数声明或定义中的一处,通常建议在声明处给出。

    四、函数重载

    C++ 支持同一作用域内同名函数,前提是形参不同(个数或类型不同)。C 语言不支持此特性。

    4.1 参数类型不同

    void Add(int a, int b) { cout << a + b << endl; }
    void Add(double a, double b) { cout << a + b << endl; }
    // 调用时根据传入类型自动匹配
    

    4.2 参数个数不同

    void fuc() { cout << "haha" << endl; }
    void fuc(int a) { cout << "hehe" << endl; }
    

    4.3 参数类型顺序不同

    void fuc(int a, char b) { cout << "haha" << endl; }
    void fuc(char b, int a) { cout << "hehe" << endl; }
    

    4.4 错误点

    • 返回值不同:不能作为重载条件,调用时无法区分。
    • 缺省参数歧义:若存在缺省参数导致调用不明确,编译器会报错。
    void f1() { cout << "f()" << endl; }
    void f1(int a = 10) { cout << "f(int a)" << endl; }
    // f1(); 此时编译器不知道调用哪个
    

    解决方法:利用命名空间隔离。

    namespace m {
        void f1(int a = 10) { cout << "f(int a)" << endl; }
    }
    // 调用时明确指定 f1() 或 m::f1()
    

    五、引用

    5.1 引用概念

    引用是变量的别名,不占用额外内存空间。

    int a = 0;
    int& b = a; // b 是 a 的别名
    int& c = b; // c 也是 a 的别名
    

    5.2 引用特性

    • 必须初始化:定义时必须绑定对象。
    • 不可更改指向:一旦引用某实体,不能再引用其他对象(赋值操作仅修改值,不改变绑定关系)。

    5.3 引用使用

    主要用于引用传参和返回,减少拷贝提高效率,或直接修改原对象。

    #include <iostream>
    #include <cstdlib>
    using namespace std;
    
    typedef int STDataType;
    typedef struct Stack {
        STDataType* a;
        int top;
        int capacity;
    } ST;
    
    void STInit(ST& rs, int n = 4) {
        rs.a = (STDataType*)malloc(n * sizeof(STDataType));
        rs.top = 0;
        rs.capacity = n;
    }
    
    void STPush(ST& rs, STDataType x) {
        if (rs.capacity == rs.top) {
            int newcapacity = (rs.capacity == 0 ? 4 : rs.capacity * 2);
            STDataType* ptr = (STDataType*)realloc(rs.a, sizeof(STDataType) * newcapacity);
            if (ptr == NULL) {
                perror("realloc");
                return;
            }
            rs.a = ptr;
            rs.capacity = newcapacity;
        }
        rs.a[rs.top++] = x;
    }
    
    int& STTop(ST& rs) {
        return rs.a[rs.top - 1];
    }
    
    void STDestroy(ST& rs) {
        if (rs.a == NULL) return;
        free(rs.a);
        rs.a = nullptr;
        rs.capacity = rs.top = 0;
    }
    
    int main() {
        ST rs;
        STInit(rs);
        STPush(rs, 1);
        STPush(rs, 2);
        cout << STTop(rs) << endl;
        STTop(rs) = 10; // 通过引用直接修改栈顶元素
        cout << STTop(rs) << endl;
        STDestroy(rs);
        return 0;
    }
    

    5.4 const 引用

    • 可以引用 const 对象,且必须用 const 引用。
    • 临时对象具有常性,若需绑定普通对象到 const 引用,可防止误修改。
    double a = 1.23;
    const int& b = a; // 隐式转换产生临时对象,必须用 const 引用
    

    六、指针和引用

    特性引用指针
    空间不开辟新空间,只是别名存储地址,开辟空间
    初始化必须初始化建议初始化,非强制
    指向可变不可变可变
    访问方式直接访问需解引用
    sizeof引用类型大小地址空间大小
    安全性较安全,极少野指针易出现空/野指针

    七、inline

    内联函数在编译时将函数体展开到调用处,省去栈帧建立开销,适合频繁调用的短小函数。递归函数或复杂函数通常会被编译器忽略。

    inline void Swap(int& a, int& b) {
        int tmp = a;
        a = b;
        b = tmp;
    }
    
    • 替代宏:相比 C 语言宏,inline 有类型检查,更安全且方便调试。
    • 声明定义分离:不建议将 inline 函数的声明和定义分离到不同文件,否则可能导致链接错误。

    八、nullptr

    8.1 问题引入

    使用 NULL 调用重载函数时,可能因 NULL 被定义为 0 而意外调用整型版本,而非指针版本。

    8.2 原因分析

    C++ 中 NULL 可能是字面常量 0,也可能是 (void*)0。这导致类型推断的不确定性。

    8.3 解决方法

    C++11 引入 nullptr 关键字。它是一个特殊类型的字面量,只能隐式转换为指针类型,不能转换为整数类型,从而彻底解决歧义。

    void fuc(int* a) { cout << "pointer" << endl; }
    void fuc(int a) { cout << "int" << endl; }
    
    int main() {
        fuc(nullptr); // 明确调用指针版本
        return 0;
    }
    

    目录

    1. 一、namespace
    2. 1.1 namespace 的引入
    3. 1.2 namespace 的定义
    4. 1.3 namespace 使用
    5. 二、输入输出
    6. 三、缺省参数
    7. 四、函数重载
    8. 4.1 参数类型不同
    9. 4.2 参数个数不同
    10. 4.3 参数类型顺序不同
    11. 4.4 错误点
    12. 五、引用
    13. 5.1 引用概念
    14. 5.2 引用特性
    15. 5.3 引用使用
    16. 5.4 const 引用
    17. 六、指针和引用
    18. 七、inline
    19. 八、nullptr
    20. 8.1 问题引入
    21. 8.2 原因分析
    22. 8.3 解决方法

    更多推荐文章

    查看全部
    • WebGPU 与 WebGL 核心差异详解
    • 云电脑部署 DeepSeek 横向对比:ToDesk、顺网云与海马云性能测试
    • C++ 伸展树与红黑树原理及实现详解
    • 大语言模型 (LLM) 产品开发流程参考
    • C++ 继承机制详解:概念、规则与菱形继承
  • 深度体验 Ling Studio:万亿参数模型重塑 AI 开发工作流
  • Claude Code 高级编程技巧与实战项目详解
  • 无人机路径规划核心算法解析:从 A*到蚁群策略
  • GitHub Copilot 插件安装与配置指南
  • JavaScript 中 =、==与===的区别详解
  • 远程控制安全与软件测评:ToDesk、AnyDesk、向日葵对比
  • Llama-3.2-3B 本地实测:中文法律理解与类案推荐效果
  • GitNexus 核心引擎深度解析
  • 基于 DeepSeek 的贪吃蛇游戏开发实战
  • Flutter web_scraper 在 OpenHarmony 下的网页抓取适配与实战
  • Stable Diffusion WebUI 本地部署教程
  • 程序员遇到问题如何寻求帮助:聪明提问指南
  • 二叉树算法实战:计算深度与先序遍历还原
  • 鸿蒙纯血版侧载第三方应用实操指南
  • JSP+SSM 健身器材管理系统设计与实现
  • 相关免费在线工具

    • 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

    • JSON 压缩

      通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

    • JSON美化和格式化

      将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online