数学, 容器适配器, 智能指针
C++ 标准库提供了丰富的数学函数库,用于执行各种数学运算。这些函数主要定义在 <cmath> 头文件中,此外还有一些特定的数学功能分布在 <cstdlib>、<complex> 等头文件中。以下是 C++ 数学库的详细介绍和一些常见操作。
1. 基本数学函数() 
Section titled “1. 基本数学函数()”<cmath> 头文件提供了常用的数学函数,如三角函数、指数函数、对数函数、幂函数、舍入函数等。
- sin:正弦函数
- cos:余弦函数
- tan:正切函数
- asin:反正弦函数
- acos:反余弦函数
- atan:反正切函数
- atan2:返回给定 x 和 y 坐标的点的极坐标角度
#include <iostream>#include <cmath>
int main() {    double angle = 45.0;    double radians = angle * M_PI / 180.0;
    std::cout << "sin(45) = " << std::sin(radians) << std::endl;    std::cout << "cos(45) = " << std::cos(radians) << std::endl;    std::cout << "tan(45) = " << std::tan(radians) << std::endl;
    return 0;}指数和对数函数
Section titled “指数和对数函数”- exp:计算 e 的 x 次幂
- log:计算自然对数(以 e 为底)
- log10:计算以 10 为底的对数
- sqrt:计算平方根
- cbrt:计算立方根
- pow:计算 x 的 y 次幂
#include <iostream>#include <cmath>
int main() {    double x = 2.0;    double y = 8.0;
    std::cout << "exp(2) = " << std::exp(x) << std::endl;    std::cout << "log(8) = " << std::log(y) << std::endl;    std::cout << "log10(8) = " << std::log10(y) << std::endl;    std::cout << "sqrt(4) = " << std::sqrt(4.0) << std::endl;    std::cout << "cbrt(8) = " << std::cbrt(8.0) << std::endl;    std::cout << "pow(2, 3) = " << std::pow(2.0, 3.0) << std::endl;
    return 0;}舍入和取整函数
Section titled “舍入和取整函数”- ceil:向上取整
- floor:向下取整
- round:四舍五入
- trunc:截断小数部分
#include <iostream>#include <cmath>
int main() {    double x = 3.14;    double y = 2.718;
    std::cout << "ceil(3.14) = " << std::ceil(x) << std::endl;    std::cout << "floor(3.14) = " << std::floor(x) << std::endl;    std::cout << "round(3.14) = " << std::round(x) << std::endl;    std::cout << "trunc(3.14) = " << std::trunc(x) << std::endl;
    return 0;}其他常用数学函数
Section titled “其他常用数学函数”- fabs:计算绝对值
- fmod:计算浮点数取模
- hypot:计算欧几里得范数,即 sqrt(xx + yy)
#include <iostream>#include <cmath>
int main() {    double x = -3.14;    double y = 2.5;
    std::cout << "fabs(-3.14) = " << std::fabs(x) << std::endl;    std::cout << "fmod(3.14, 2.0) = " << std::fmod(3.14, 2.0) << std::endl;    std::cout << "hypot(3, 4) = " << std::hypot(3.0, 4.0) << std::endl;
    return 0;}2. 随机数生成() 
Section titled “2. 随机数生成()”<cstdlib> 头文件提供了随机数生成函数,如 rand 和 srand。
#include <iostream>#include <cstdlib>#include <ctime>
int main() {    std::srand(static_cast<unsigned int>(std::time(nullptr)));
    for (int i = 0; i < 5; ++i) {        std::cout << "Random number " << i + 1 << ": " << std::rand() << std::endl;    }
    return 0;}3. 复数运算() 
Section titled “3. 复数运算()”<complex> 头文件提供了用于复数运算的类模板 std::complex 及相关函数。
#include <iostream>#include <complex>
int main() {    std::complex<double> c1(1.0, 2.0);    std::complex<double> c2(2.0, 1.0);
    std::complex<double> c3 = c1 + c2;    std::complex<double> c4 = c1 * c2;
    std::cout << "c1 + c2 = " << c3 << std::endl;    std::cout << "c1 * c2 = " << c4 << std::endl;    std::cout << "abs(c1) = " << std::abs(c1) << std::endl;    std::cout << "arg(c1) = " << std::arg(c1) << std::endl;    std::cout << "norm(c1) = " << std::norm(c1) << std::endl;    std::cout << "conj(c1) = " << std::conj(c1) << std::endl;
    return 0;}4. 数学常量(C++20 引入)
Section titled “4. 数学常量(C++20 引入)”C++20 引入了 <numbers> 头文件,提供了一些常用的数学常量。
#include <iostream>#include <numbers>
int main() {    std::cout << "Pi = " << std::numbers::pi << std::endl;    std::cout << "Euler's number (e) = " << std::numbers::e << std::endl;    std::cout << "Golden ratio = " << std::numbers::phi << std::endl;
    return 0;}在 C++ 标准模板库(STL)中,容器适配器(Container Adapters)是一组用于修改或限制其他标准容器接口的类模板。容器适配器本质上是对基础容器进行封装,提供不同的接口或行为,使其更符合特定的需求。C++ 提供了三种主要的容器适配器:stack、queue 和 priority_queue。
1. stack
Section titled “1. stack”stack 是一种后进先出(LIFO, Last-In-First-Out)的数据结构,只允许在栈顶进行插入和删除操作。stack 默认使用 deque 作为底层容器,但也可以使用 vector 或 list。
常用成员函数
Section titled “常用成员函数”- push:向栈顶添加元素。
- pop:移除栈顶元素。
- top:返回栈顶元素。
- empty:检查栈是否为空。
- size:返回栈中元素的个数。
#include <iostream>#include <stack>
int main() {    std::stack<int> s;
    s.push(10);    s.push(20);    s.push(30);
    std::cout << "Stack size: " << s.size() << std::endl;
    while (!s.empty()) {        std::cout << "Top element: " << s.top() << std::endl;        s.pop();    }
    return 0;}2. queue
Section titled “2. queue”queue 是一种先进先出(FIFO, First-In-First-Out)的数据结构,只允许在队列的末尾插入元素,在队列的前端移除元素。queue 默认使用 deque 作为底层容器,但也可以使用 list。
常用成员函数
Section titled “常用成员函数”- push:向队列末尾添加元素。
- pop:移除队列前端元素。
- front:返回队列前端元素。
- back:返回队列末尾元素。
- empty:检查队列是否为空。
- size:返回队列中元素的个数。
#include <iostream>#include <queue>
int main() {    std::queue<int> q;
    q.push(10);    q.push(20);    q.push(30);
    std::cout << "Queue size: " << q.size() << std::endl;
    while (!q.empty()) {        std::cout << "Front element: " << q.front() << std::endl;        q.pop();    }
    return 0;}3. priority_queue
Section titled “3. priority_queue”priority_queue 是一种优先级队列,元素按优先级顺序排序(默认是最大优先级在前)。priority_queue 默认使用 vector 作为底层容器,并使用 std::make_heap、std::push_heap 和 std::pop_heap 维护堆的性质。
常用成员函数
Section titled “常用成员函数”- push:向优先级队列中添加元素。
- pop:移除优先级最高的元素。
- top:返回优先级最高的元素。
- empty:检查优先级队列是否为空。
- size:返回优先级队列中元素的个数。
#include <iostream>#include <queue>#include <vector>
int main() {    std::priority_queue<int> pq;
    pq.push(30);    pq.push(10);    pq.push(20);
    std::cout << "Priority queue size: " << pq.size() << std::endl;
    while (!pq.empty()) {        std::cout << "Top element: " << pq.top() << std::endl;        pq.pop();    }
    return 0;}4. 自定义比较函数的 priority_queue
Section titled “4. 自定义比较函数的 priority_queue”可以通过提供自定义比较函数来改变 priority_queue 的排序行为,例如将其变为最小优先级队列。
#include <iostream>#include <queue>#include <vector>#include <functional>
int main() {    // 使用 greater<int> 创建最小优先级队列    std::priority_queue<int, std::vector<int>, std::greater<int>> pq;
    pq.push(30);    pq.push(10);    pq.push(20);
    std::cout << "Priority queue size: " << pq.size() << std::endl;
    while (!pq.empty()) {        std::cout << "Top element: " << pq.top() << std::endl;        pq.pop();    }
    return 0;}在 C++ 中,智能指针是一种用于自动管理动态分配内存的工具,它通过自动管理对象的生命周期来防止内存泄漏和未定义行为。C++11 标准引入了三种主要的智能指针:std::unique_ptr、std::shared_ptr 和 std::weak_ptr。它们都在 <memory> 头文件中定义。
1. std::unique_ptr
Section titled “1. std::unique_ptr”std::unique_ptr 是一种独占所有权的智能指针,表示某一时刻只有一个智能指针可以拥有所指向对象的所有权。它不能被复制,但可以通过移动语义转移所有权。
主要成员函数
Section titled “主要成员函数”- operator*和- operator->:访问所指向的对象。
- get:返回原始指针。
- release:放弃所有权并返回原始指针。
- reset:释放当前对象并可选择重新管理一个新对象。
#include <iostream>#include <memory>
int main() {    std::unique_ptr<int> ptr1 = std::make_unique<int>(10);    std::cout << "Value: " << *ptr1 << std::endl;
    // 转移所有权    std::unique_ptr<int> ptr2 = std::move(ptr1);    if (ptr1 == nullptr) {        std::cout << "ptr1 is null" << std::endl;    }    std::cout << "Value: " << *ptr2 << std::endl;
    // 重置指针    ptr2.reset();    if (ptr2 == nullptr) {        std::cout << "ptr2 is null" << std::endl;    }
    return 0;}2. std::shared_ptr
Section titled “2. std::shared_ptr”std::shared_ptr 是一种共享所有权的智能指针,多个智能指针可以共享同一个对象。当最后一个共享所有权的智能指针被销毁时,对象才会被释放。
主要成员函数
Section titled “主要成员函数”- operator*和- operator->:访问所指向的对象。
- get:返回原始指针。
- use_count:返回共享的智能指针数量。
- reset:释放当前对象并可选择重新管理一个新对象。
#include <iostream>#include <memory>
int main() {    std::shared_ptr<int> ptr1 = std::make_shared<int>(20);    std::cout << "Value: " << *ptr1 << std::endl;    std::cout << "Use count: " << ptr1.use_count() << std::endl;
    {        std::shared_ptr<int> ptr2 = ptr1;        std::cout << "Value: " << *ptr2 << std::endl;        std::cout << "Use count: " << ptr1.use_count() << std::endl;    }
    std::cout << "Use count after ptr2 is out of scope: " << ptr1.use_count() << std::endl;
    return 0;}3. std::weak_ptr
Section titled “3. std::weak_ptr”std::weak_ptr 是一种不控制对象生命周期的智能指针,它必须与 std::shared_ptr 一起使用。std::weak_ptr 主要用于打破循环引用,因为它不增加引用计数。
主要成员函数
Section titled “主要成员函数”- lock:创建一个- std::shared_ptr,如果对象已经被销毁,返回一个空的- std::shared_ptr。
- expired:检查对象是否已被销毁。
- use_count:返回共享的智能指针数量。
#include <iostream>#include <memory>
int main() {    std::shared_ptr<int> sptr = std::make_shared<int>(30);    std::weak_ptr<int> wptr = sptr;
    std::cout << "Use count: " << sptr.use_count() << std::endl;
    if (auto temp_sptr = wptr.lock()) {        std::cout << "Value: " << *temp_sptr << std::endl;        std::cout << "Use count: " << temp_sptr.use_count() << std::endl;    } else {        std::cout << "The object has been destroyed." << std::endl;    }
    sptr.reset();    if (wptr.expired()) {        std::cout << "The object has been destroyed." << std::endl;    }
    return 0;}- std::unique_ptr:适用于唯一所有权的资源管理,如动态分配的数组或对象,避免内存泄漏。
- std::shared_ptr:适用于需要共享所有权的资源管理,如共享的资源或对象池。
- std::weak_ptr:适用于打破循环引用,辅助- std::shared_ptr管理对象生命周期。