C++入门基础

目录

[一、C++ 发展与版本更新](#一、C++ 发展与版本更新)

[1. 发展起源](#1. 发展起源)

[二、C++ 核心基础语法(入门必掌握)](#二、C++ 核心基础语法(入门必掌握))

[1. 第一个 C++ 程序:Hello World](#1. 第一个 C++ 程序:Hello World)

[2. 命名空间(namespace):解决命名冲突](#2. 命名空间(namespace):解决命名冲突)

[3. C++ 输入输出(cin/cout)](#3. C++ 输入输出(cin/cout))

[4. 缺省参数(默认参数):函数参数的默认值](#4. 缺省参数(默认参数):函数参数的默认值)

[5. 函数重载:C++ 的多态特性(入门)](#5. 函数重载:C++ 的多态特性(入门))

[6. 引用(&):变量的别名(C++ 核心语法,必吃透)](#6. 引用(&):变量的别名(C++ 核心语法,必吃透))

[7. 内联函数(inline):替代 C 语言宏函数](#7. 内联函数(inline):替代 C 语言宏函数)

[8. nullptr:C++11 的空指针常量](#8. nullptr:C++11 的空指针常量)

[三、C++ 参考文档(开发必备)](#三、C++ 参考文档(开发必备))

一、C++ 发展与版本更新

1. 发展起源

C++ 由本贾尼・斯特劳斯特卢普 于 1979 年在贝尔实验室研发,初衷是解决 C 语言在面向对象、可维护性、可扩展性上的不足,1983 年正式命名为 C++,1998 年发布第一个 ANSI/ISO 官方标准(C++98),并引入 STL(标准模板库)成为核心特性

二、C++ 核心基础语法(入门必掌握)

C++ 兼容 C 语言绝大多数语法,但新增了面向对象、命名空间、引用、函数重载等核心特性,以下是入门阶段必须吃透的语法点,按 "基础到进阶" 排序。

1. 第一个 C++ 程序:Hello World

C++ 有C 语言兼容版原生版 两种写法,核心区别是输入输出流 ,原生版使用 C++ 的iostream库,无需手动指定格式,更符合 C++ 特性。

cpp 复制代码
// C++原生版Hello World
#include<iostream>
using namespace std; // 展开标准命名空间,方便使用cout/endl
int main()
{
    cout << "hello world" << endl; // cout=输出流,endl=换行+刷新缓冲区
    return 0;
}

编译注意 :C++ 文件后缀为.cpp,Windows(VS)自动调用 C++ 编译器,Linux 需用g++编译(而非 C 的gcc)。

2. 命名空间(namespace):解决命名冲突

核心问题

C 语言中所有变量、函数都在全局作用域 ,容易出现重定义(如自定义rand和库函数rand冲突),C++ 引入namespace实现作用域隔离

核心特性

  1. 命名空间是独立的域,与全局域、局部域、类域分离,不同域可定义同名标识符;
  2. 只能定义在全局作用域,支持嵌套定义 ,多文件中同名命名空间会自动合并
  3. C++ 标准库的所有内容都在std命名空间中(如 cout、cin、STL 容器)。

三种使用方式:

使用方式 语法 适用场景 推荐度
指定命名空间 xh::rand 项目开发(避免冲突) ✅✅✅(强烈推荐)
展开单个成员 using xh::Add 频繁使用的单个成员,无冲突风险 ✅✅
展开全部成员 using namespace xh 日常小练习(方便快捷) ❌(项目禁止,冲突风险极高)

示例:解决 rand 重定义问题

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
namespace xh // 自定义命名空间
{
    int rand = 10; // 与库函数rand不冲突
}
int main()
{
    printf("%p\n", rand); // 访问全局库函数rand
    printf("%d\n", xh::rand); // 访问bit命名空间的rand
    return 0;
}

3. C++ 输入输出(cin/cout)

基于<iostream>库,核心是流插入(<<)**和**流提取(>>) ,相比 C 的printf/scanf有 2 个核心优势:

  1. 自动识别变量类型 ,无需手动指定%d/%lf/%c等格式符;
  2. 更好支持自定义类型(如类对象的输入输出,后续面向对象重点)。
cpp 复制代码
#include<iostream>
using namespace std;
int main()
{
    int a = 0;
    double b = 0.1;
    char c = 'x';
    cin >> a >> b >> c; // 输入,自动识别类型
    cout << a << " " << b << " " << c << endl; // 输出,endl换行
    return 0;
}

性能优化(竞赛 / 大量输入场景)

C++IO 流默认与 C 标准 IO 同步,效率较低,添加以下代码可关闭同步,提升效率:

cpp 复制代码
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);

4. 缺省参数(默认参数):函数参数的默认值

定义:

声明 / 定义函数时为参数指定默认值,调用时若不传该参数,则使用默认值;若传参,则使用实参。

分类

  1. 全缺省:所有参数都指定默认值;
  2. 半缺省 :部分参数指定默认值,必须从右往左连续指定,不能间隔(C++ 语法强制要求)。
cpp 复制代码
#include <iostream>
using namespace std;

// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

// 半缺省
void Func2(int a, int b = 10, int c = 20)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

int main()
{
	Func1();
	Func1(1);
	Func1(1, 2);
	Func1(1, 2, 3);
	Func2(100);
	Func2(100, 200);
	Func2(100, 200, 300);
	return 0;
}

核心规则

  1. 函数调用时,实参必须从左到右依次传递,不能跳跃传参;
  2. 函数声明和定义分离 时,缺省参数只能在声明中指定(头文件),定义中不能重复(避免二义性)。

示例:栈初始化的缺省参数(实战常用)

cpp 复制代码
// 头文件Stack.h(声明)
typedef int STDataType;
typedef struct Stack {
    STDataType* a;
    int top;
    int capacity;
}ST;
void STInit(ST* ps, int n = 4); // 半缺省,n默认值4

// 源文件Stack.cpp(定义)
void STInit(ST* ps, int n) // 不能再写n=4
{
    ps->a = (STDataType*)malloc(n * sizeof(STDataType));
    ps->top = 0;
    ps->capacity = n;
}

// 调用
int main()
{
    ST s1;
    STInit(&s1); // 不传n,使用默认值4
    ST s2;
    STInit(&s2, 1000); // 传n,使用实参1000(避免扩容,提升效率)
    return 0;
}

5. 函数重载:C++ 的多态特性(入门)

定义:

同一作用域 中,函数名相同 ,但形参列表不同参数个数 / 类型 / 顺序不同)的多个函数,称为函数重载,C 语言不支持(因为 C 语言通过函数名唯一标识函数)。

核心规则

  1. 返回值不同不能作为重载条件(调用时编译器无法区分);
  2. 缺省参数可能导致重载歧义(如无参函数和单缺省参数函数,调用时不传参会报错);
  3. 形参的const/volatile 属性不同,可作为重载条件(后续进阶)。

示例:函数重载的三种合法形式

cpp 复制代码
#include<iostream>
using namespace std;
// 1. 参数类型不同
int Add(int a, int b) { return a + b; }
double Add(double a, double b) { return a + b; }

// 2. 参数个数不同
void f() { cout << "无参f" << endl; }
void f(int a) { cout << "单参f" << endl; }

// 3. 参数顺序不同
void f(int a, char b) { cout << "int+char" << endl; }
void f(char b, int a) { cout << "char+int" << endl; }

int main()
{
    Add(1,2); // 调用int版Add
    Add(1.1,2.2); // 调用double版Add
    f(); // 调用无参f
    f(1); // 调用单参f
    f(1, 'a'); // 调用int+char版f
    f('a', 1); // 调用char+int版f
    return 0;
}

6. 引用(&):变量的别名(C++ 核心语法,必吃透)

定义:

引用不是新定义变量,而是给已存在的变量取别名 ,编译器不为引用开辟内存,引用和原变量共用同一块内存空间 ,语法:类型& 引用名 = 原变量;

三大核心特性(语法强制要求,记死)

  1. 定义时必须初始化(不能先定义后赋值);
  2. 一个变量可以有多个别名(多个引用指向同一个变量);
  3. 引用一旦指向某个变量,就不能再指向其他变量(终身绑定)。

基础示例

cpp 复制代码
#include<iostream>
using namespace std;
int main()
{
    int a = 10;
    int& b = a; // b是a的别名
    int& c = a; // c也是a的别名
    b = 20; // 修改变名,原变量也改变
    cout << a << " " << b << " " << c << endl; // 输出20 20 20
    cout << &a << " " << &b << " " << &c << endl; // 地址完全相同
    return 0;
}

错误例子(改变已经引用的变量):

实战用途(核心:减少拷贝 + 修改原变量,替代指针的部分场景)

1引用传参:替代指针,简化代码,同时实现 "修改原变量" 的效果(如交换函数、栈操作)

cpp 复制代码
#include <iostream>
using namespace std;

// 引用传参实现交换,无需指针,更简洁
void Swap(int& x, int& y)
{
    int tmp = x;  // 保存x的原始值
    x = y;        // 将y的值赋给x(直接操作原变量)
    y = tmp;      // 将原始x的值赋给y(直接操作原变量)
}

int main()
{
    // 1. 定义两个待交换的变量
    int a = 10, b = 20;
    
    // 2. 打印交换前的值
    cout << "交换前: a = " << a << ", b = " << b << endl;
    
    // 3. 调用Swap函数(直接传变量名,无需取地址)
    Swap(a, b);
    
    // 4. 打印交换后的值,验证交换效果
    cout << "交换后: a = " << a << ", b = " << b << endl;
    
    return 0;
}

2引用返回值:函数返回值为引用,可直接修改返回的变量,同时减少值拷贝的性能损耗(如栈顶元素获取);

3替代二级指针 :在链表 / 树的开发中,用指针的引用 (如LTNode*& phead)替代二级指针,简化代码。

const 引用(常引用):权限的控制

核心是控制变量的访问权限 ,C++ 中引用的权限只能缩小,不能放大,这是 const 引用的核心规则:

  1. 普通引用:只能指向普通变量,不能指向 const 变量(权限放大,编译报错);
  2. const 引用 :可以指向const 变量 (权限匹配),也可以指向普通变量(权限缩小),但不能通过 const 引用修改原变量;
  3. 临时对象 :表达式计算(如a*3)、类型转换(如double→int)会产生临时对象 ,临时对象具有常性,只能用 const 引用指向。

示例:const 引用的合法 / 非法使用

cpp 复制代码
#include <iostream>
using namespace std;
int main()
{
    const int a = 10;
    //a= 20; // 非法:常量不能修改值
    // int& ra = a; // 非法:权限放大(普通引用指向const变量)
    const int& ra = a; // 合法:权限匹配
    // ra = 20; // 非法:不能通过const引用修改原变量
    cout << a << " " << ra << endl; // 输出:10 10
 

    int b = 20;
    b = 30; // 合法:普通变量可以修改值
    const int& rb = b; // 合法:权限缩小(const引用指向普通变量)
    // rb = 30; // 非法:不能通过const引用修改原变量
    b= 40; // 合法:普通变量可以修改值
    cout << b << " " << rb << endl; // 输出:40 40

    // int& rc = b*3; // 非法:临时对象具有常性,普通引用不能指向
    const int& rc = b * 3; // 合法:const引用指向临时对象
    cout << rc << endl; // 输出:120

    double d = 12.34;
    // int& rd = d; // 非法:类型转换产生临时对象,普通引用不能指向
    const int& rd = d; // 合法:const引用指向临时对象

    // 常量表达式
    //int& rf = 30;//非法:非常量引用的初始值必须为左值
    const int& rf = 30;//合法:常量表达式可以作为左值
    cout << rf << endl; // 输出:30

    return 0;
}

引用与指针的区别(入门必背,理解核心差异)

C++ 中引用和指针功能重叠,但互相不可替代,核心差异如下:

特性 引用 指针
内存开辟 不开辟,只是别名 开辟内存,存储变量地址
初始化 定义时必须初始化 语法上不强制初始化(建议初始化)
指向修改 一旦绑定,不能修改指向 可以随时修改指向的变量
访问方式 直接访问(如b = 20 解引用访问(如*p = 20
sizeof 含义 引用类型的大小(如int&为 4) 地址的大小(32 位 4 字节,64 位 8 字节)
安全性 无空引用 / 野引用,更安全 有空指针 / 野指针,风险较高

7. 内联函数(inline):替代 C 语言宏函数

定义:

inline修饰的函数,编译时编译器会在调用处直接展开函数体 ,无需建立栈帧,从而提升函数调用效率

核心特性

  1. 编译器的建议inline只是给编译器的 "建议",编译器可拒绝展开(如递归函数、代码量过大的函数);
  2. 适用场景频繁调用的短小函数(如 Add、Swap),递归 / 长函数加 inline 会被编译器忽略;
  3. 声明定义不能分离 :inline 函数若在头文件声明、源文件定义,会导致链接错误(因为函数被展开,无函数地址);
  4. 替代 C 宏函数 :C 语言宏函数通过预处理展开,无类型检查、易出错、不方便调试,inline 函数保留宏的效率,同时具备函数的类型检查、调试友好特性。

示例:inline 函数的使用

cpp 复制代码
#include<iostream>
using namespace std;
// 频繁调用的短小函数,加inline提升效率
inline int Add(int x, int y)
{
    return x + y;
}
int main()
{
    int ret = Add(1,2); // 编译时直接展开为ret = 1+2,无栈帧建立
    return 0;
}

宏版本的实现代码

cpp 复制代码
#include<iostream>
using namespace std;

// 定义加法宏函数(注意:宏的结尾不能加分号)
#define ADD(x, y) ((x) + (y))

int main()
{
    int ret = ADD(1, 2); // 预处理阶段直接替换为 ((1) + (2))
    cout << "ret = " << ret << endl; // 输出:ret = 3

    // 扩展示例:验证宏的替换特性(也能看出宏的坑)
    int a = 10, b = 20;
    int ret2 = ADD(a++, b++); // 替换为 ((a++) + (b++)),a和b会被自增1次!
    cout << "ret2 = " << ret2 << endl; // 输出:ret2 = 30
    cout << "a = " << a << ", b = " << b << endl; // 输出:a = 11, b = 21
    return 0;
}

宏的核心特性

  • 宏是预处理阶段 (编译前)进行文本替换 ,而非函数调用,因此也没有栈帧建立的开销(这是宏和inline的共同优点);
  • 宏定义的语法:#define 宏名(参数) 替换内容结尾不能加分号(否则替换后会多加分号导致语法错误);
  • 替换内容和参数必须加足够的括号(比如上面的((x) + (y))),否则会因运算符优先级导致错误(比如ADD(1+2, 3*4)如果不加括号会变成1+2+3*4,结果不符合预期)。

8. nullptr:C++11 的空指针常量

问题背景

C 语言中的NULL ,在 C++ 中被定义为0,导致函数重载的歧义 (如调用f(int*)时,传NULL会被解析为0,调用f(int))。

核心特性

  1. nullptr是 C++11 的关键字 ,是特殊的空指针字面量
  2. 只能被隐式转换为指针类型,不能转换为整数类型,彻底解决 NULL 的歧义问题;
  3. 所有需要表示 "空指针" 的场景,都用nullptr替代NULL(C++11 及以后推荐)。

示例:nullptr 解决重载歧义

cpp 复制代码
#include<iostream>
using namespace std;
void f(int x) { cout << "f(int)" << endl; }
void f(int* p) { cout << "f(int*)" << endl; }
int main()
{
    f(0); // 调用f(int)
    f(NULL); // 调用f(int)(因为NULL=0)
    f((int*)NULL); // 强制转换,调用f(int*)
    f(nullptr); // 调用f(int*)(正确的空指针用法,C++11推荐)
    return 0;
}

三、C++ 参考文档(开发必备)

推荐 3 个核心文档,按需使用,优先使用 cppreference(官方)

  1. legacy.cplusplus.com:非官方,仅更新到 C++11,优点是按头文件组织,易看易懂,适合入门;
  2. C++ 官方文档中文版:官方,更新到最新标准,信息最全,适合进阶 / 开发;
  3. C++ 官方文档英文版:官方原版,内容最准确,适合查阅英文原版定义。
相关推荐
huaweichenai2 小时前
java的数据类型介绍
java·开发语言
你真是饿了2 小时前
10.list
c++·list
tankeven2 小时前
HJ139 小红的01子序列计数(hard)
c++·算法
weixin_649555672 小时前
C语言程序设计第四版(何钦铭、颜晖)第十章函数与程序设计之汉诺塔问题
c语言·c++·算法
C羊驼2 小时前
C语言:随机数
c语言·开发语言·经验分享·笔记·算法
fengfuyao9852 小时前
CH552多功能音量调节旋钮设计与实现
c语言·开发语言
xushichao19892 小时前
实时数据压缩库
开发语言·c++·算法
minji...2 小时前
Linux 文件系统 (三) 软连接和硬链接
linux·运维·服务器·c++·算法
liurunlin8882 小时前
Go环境搭建(vscode调试)
开发语言·vscode·golang