C++ 快速入门指南

本文针对初学者,介绍 C++ 的基本使用,包括控制语句、标准库的常用数据结构等,以便快速上手编程和算法练习。

目录

标准输出

C++ 的标准输出是 cout,用 << 运算符把需要打印的内容传递给 coutendl 是换行符。

#include <iostream>
using namespace std;

int main() {
    int a = 10;
    
    // 输出:10
    cout << a << endl;
    
    // 可以串联输出
    // 输出:Hello, World!
    cout << "Hello" << ", " << "World!" << endl;
    
    string s = "abc";
    // 输出:abc 10
    cout << s << " " << a << endl;
    
    return 0;
}

C 语言的 printf 函数也可以用,但 cout 更加方便,推荐使用。

控制语句

条件判断

int a = 10;

if (a > 5) {
    cout << "a > 5" << endl;
} else if (a == 5) {
    cout << "a == 5" << endl;
} else {
    cout << "a < 5" << endl;
}
// 输出:a > 5

循环

for 循环一般用于已知循环次数的情况,while 循环一般用于未知循环次数的情况。

// 0 1 2 3 4
for (int i = 0; i < 5; i++) {
    cout << i << " ";
}

int num = 100;
// 100 50 25 12 6 3 1
while (num > 0) {
    cout << num << " ";
    num /= 2;
}

基本数据结构

动态数组 vector

vector 是 C++ 标准库的动态数组,比 C 语言的静态数组更加方便和安全。

初始化方法

#include <vector>

int n = 7, m = 8;

// 初始化一个 int 型的空数组
vector<int> nums;

// 初始化一个大小为 n 的数组,默认值为 0
vector<int> nums(n);

// 初始化包含指定元素的数组
vector<int> nums{1, 3, 5};

// 初始化大小为 n 且值都为 2 的数组
vector<int> nums(n, 2);

// 初始化二维数组
vector<vector<int>> dp;

// 初始化大小为 m * n 的布尔数组,初始值为 true
vector<vector<bool>> dp(m, vector<bool>(n, true));

常用操作

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n = 10;
    vector<int> nums(n);
    
    // 检查是否为空
    cout << nums.empty() << endl;  // 0 (false)
    
    // 获取大小
    cout << nums.size() << endl;   // 10
    
    // 尾部插入元素
    nums.push_back(20);
    cout << nums.size() << endl;   // 11
    
    // 获取最后一个元素
    cout << nums.back() << endl;   // 20
    
    // 删除最后一个元素
    nums.pop_back();
    cout << nums.size() << endl;   // 10
    
    // 通过索引访问和修改
    nums[0] = 11;
    cout << nums[0] << endl;       // 11
    
    // 在指定位置插入元素
    nums.insert(nums.begin() + 3, 99);
    
    // 删除指定位置元素
    nums.erase(nums.begin() + 2);
    
    // 交换元素
    swap(nums[0], nums[1]);
    
    // 遍历数组
    for (int i = 0; i < nums.size(); i++) {
        cout << nums[i] << " ";
    }
    cout << endl;
    
    return 0;
}

双链表 list

list 是 C++ 标准库中的双向链表容器。

初始化方法

#include <list>

int n = 7;

// 初始化空链表
std::list<int> lst;

// 初始化大小为 n 的链表,默认值为 0
std::list<int> lst(n);

// 初始化包含指定元素的链表
std::list<int> lst{1, 3, 5};

// 初始化大小为 n 且值都为 2 的链表
std::list<int> lst(n, 2);

常用操作

#include <iostream>
#include <list>
using namespace std;

int main() {
    list<int> lst{1, 2, 3, 4, 5};

    // 检查是否为空
    cout << lst.empty() << endl;  // false
    
    // 获取大小
    cout << lst.size() << endl;   // 5
    
    // 头部插入
    lst.push_front(0);
    // 尾部插入
    lst.push_back(6);
    
    // 获取头尾元素
    cout << lst.front() << " " << lst.back() << endl;  // 0 6
    
    // 删除头尾元素
    lst.pop_front();
    lst.pop_back();
    
    // 在指定位置插入
    auto it = lst.begin();
    advance(it, 2);        // 移动到第三个位置
    lst.insert(it, 99);    // 插入元素
    
    // 删除指定位置元素
    it = lst.begin();
    advance(it, 1);        // 移动到第二个位置
    lst.erase(it);         // 删除元素
    
    // 遍历链表
    for (int val : lst) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}

队列 queue

queue 基于先进先出(FIFO)原则,适用于从队尾添加、队头移除元素的场景。

#include <iostream>
#include <queue>
using namespace std;

int main() {
    queue<int> q;

    // 添加元素
    q.push(10);
    q.push(20);
    q.push(30);

    // 检查是否为空
    cout << q.empty() << endl;  // false
    
    // 获取大小
    cout << q.size() << endl;   // 3
    
    // 获取队头和队尾元素
    cout << q.front() << " " << q.back() << endl;  // 10 30
    
    // 删除队头元素
    q.pop();
    cout << q.front() << endl;  // 20

    return 0;
}

栈 stack

栈基于后进先出(LIFO)原则,适用于在栈顶添加或移除元素的场景。

#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> s;

    // 向栈顶添加元素
    s.push(10);
    s.push(20);
    s.push(30);

    // 检查是否为空
    cout << s.empty() << endl;  // false
    
    // 获取大小
    cout << s.size() << endl;   // 3
    
    // 获取栈顶元素
    cout << s.top() << endl;    // 30
    
    // 删除栈顶元素
    s.pop();
    cout << s.top() << endl;    // 20

    return 0;
}

哈希表 unordered_map

unordered_map 提供基于键值对的存储,支持常数时间复杂度的查找、插入和删除操作。

初始化方法

#include <unordered_map>
using namespace std;

// 初始化空哈希表
unordered_map<int, string> hashmap;

// 初始化包含键值对的哈希表
unordered_map<int, string> hashmap{{1, "one"}, {2, "two"}, {3, "three"}};

常用操作

#include <iostream>
#include <unordered_map>
using namespace std;

int main() {
    unordered_map<int, string> hashmap{{1, "one"}, {2, "two"}, {3, "three"}};

    // 检查是否为空
    cout << hashmap.empty() << endl;  // 0 (false)
    
    // 获取大小
    cout << hashmap.size() << endl;   // 3
    
    // 查找键是否存在(C++20)
    if (hashmap.contains(2)) {
        cout << "Key 2 -> " << hashmap[2] << endl;  // Key 2 -> two
    }
    
    // 访问不存在的键会自动创建(重要!)
    cout << hashmap[4] << endl;  // 空字符串,同时创建了键4
    
    // 插入键值对
    hashmap[4] = "four";
    
    // 删除键值对
    hashmap.erase(3);
    
    // 遍历哈希表
    for (const auto &pair : hashmap) {
        cout << pair.first << " -> " << pair.second << endl;
    }

    return 0;
}

重要提醒:访问不存在的键会自动创建该键,这可能导致意外的行为。

哈希集合 unordered_set

unordered_set 用于存储不重复的元素,常用于元素去重。

初始化方法

#include <unordered_set>
using namespace std;

// 初始化空集合
unordered_set<int> uset;

// 初始化包含元素的集合
unordered_set<int> uset{1, 2, 3, 4};

常用操作

#include <iostream>
#include <unordered_set>
using namespace std;

int main() {
    unordered_set<int> hashset{1, 2, 3, 4};

    // 检查是否为空
    cout << hashset.empty() << endl;  // 0 (false)
    
    // 获取大小
    cout << hashset.size() << endl;   // 4
    
    // 查找元素是否存在
    if (hashset.contains(3)) {
        cout << "Element 3 found." << endl;
    }
    
    // 插入元素
    hashset.insert(5);
    
    // 删除元素
    hashset.erase(2);
    
    // 遍历集合
    for (const auto &element : hashset) {
        cout << element << endl;
    }

    return 0;
}

函数参数传递

传值

传值将参数的副本传递给函数,函数内的修改不会影响原始数据。

#include <iostream>
using namespace std;

void modifyValue(int x) {
    x = 10;  // 只修改副本
}

int main() {
    int num = 5;
    modifyValue(num);
    cout << "After modifyValue, num = " << num << endl;  // 5
    return 0;
}

传引用

传引用将参数的地址传递给函数,函数可以直接操作原始数据。

#include <iostream>
using namespace std;

void modifyReference(int &x) {
    x = 10;  // 修改原始数据
}

int main() {
    int num = 5;
    modifyReference(num);
    cout << "After modifyReference, num = " << num << endl;  // 10
    return 0;
}

使用建议

  1. 基本类型(int、bool 等):通常使用传值,因为复制开销小
  2. 容器类型(vector、unordered_map 等):通常使用传引用,避免复制开销
  3. 重要提醒:递归函数中的容器参数切勿使用传值,否则每次递归都会创建副本,导致性能问题
// 推荐:传引用
void processVector(vector<int>& nums) {
    // 处理逻辑
}

// 避免:传值(性能差)
void processVectorSlow(vector<int> nums) {
    // 处理逻辑
}