AI算法C++学习笔记--高级C++特性

  • STL(标准模板库):熟练使用STL中的容器(如vector、list、map等)、迭代器、算法和函数对象。

  • 异常处理:了解如何使用异常处理机制来提高程序的健壮性。

  • 智能指针:掌握智能指针(如unique_ptr、shared_ptr、weak_ptr)的使用,以避免内存泄漏和提高资源管理的安全性。

  • 多线程编程:理解并能够使用C++11及以后版本中的多线程库,如std::thread、std::mutex、std::future等。


STL(标准模板库)

C++标准模板库(STL)提供了一系列的容器、迭代器、算法和函数对象,它们是构建高效、可重用代码的基础组件。下面是这些组件的基本使用方法:

容器(Containers)

容器是用来存储数据的数据结构。STL提供了多种容器,包括序列容器(如vector、list、deque)和关联容器(如set、map、unordered_set、unordered_map)。

vector
vector是一个动态数组,支持随机访问。

#include <vector>

int main() {
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);

    for (size_t i = 0; i < v.size(); ++i) {
        std::cout << v[i] << " ";
    }
    std::cout << std::endl;

    return 0;
}

list
list是一个双向链表,不支持随机访问,但插入和删除操作很快。

#include <list>

int main() {
    std::list<int> l;
    l.push_back(1);
    l.push_front(2);
    l.push_back(3);

    for (auto it = l.begin(); it != l.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

map
map是一个关联容器,它存储键值对,并根据键自动排序。

#include <map>

int main() {
    std::map<std::string, int> m;
    m["one"] = 1;
    m["two"] = 2;
    m["three"] = 3;

    for (auto it = m.begin(); it != m.end(); ++it) {
        std::cout << it->first << ": " << it->second << std::endl;
    }

    return 0;
}

迭代器(Iterators)

迭代器是用于遍历容器中元素的对象。它们提供了一种统一的方式来访问容器中的元素,而不需要了解容器的内部实现。

#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3};
    for (auto it = v.begin(); it != v.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

算法(Algorithms)

STL提供了大量的算法,这些算法可以作用于各种容器。它们通常通过迭代器来访问容器中的元素。

#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {3, 1, 2};
    std::sort(v.begin(), v.end());

    for (auto it = v.begin(); it != v.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

函数对象(Function Objects)

函数对象(也称为仿函数)是重载了函数调用运算符()的对象。它们可以像函数一样被调用,并且可以存储状态。

#include <vector>
#include <algorithm>

struct Compare {
    bool operator()(int a, int b) const {
        return a < b;
    }
};

int main() {
    std::vector<int> v = {3, 1, 2};
    std::sort(v.begin(), v.end(), Compare());

    for (auto it = v.begin(); it != v.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,Compare是一个函数对象,它定义了一个比较操作,用于std::sort算法。

总结
STL的容器、迭代器、算法和函数对象是C++泛型编程的核心组件。它们提供了一种高效、可重用的方式来处理数据,使得程序员可以专注于算法的设计,而不需要重复实现基本的数据结构和操作。通过合理地使用STL,可以显著提高代码的质量和开发效率。

异常处理

在C++中,异常处理机制是一种用于处理程序运行时错误的强大工具,它可以帮助提高程序的健壮性。通过合理地使用异常处理,可以确保程序在遇到不可预见的错误时能够优雅地处理,而不是直接崩溃。以下是C++中异常处理的基本概念和使用方法:

基本概念

异常(Exception):程序运行时出现的错误或异常情况。

抛出异常(Throwing an Exception):当检测到异常情况时,使用throw关键字抛出一个异常对象。

捕获异常(Catching an Exception):使用try和catch块来捕获并处理异常。

异常类(Exception Classes):可以自定义异常类,也可以使用标准异常类。

基本语法

try {
    // 可能抛出异常的代码
} catch (exceptionType1& e) {
    // 处理 exceptionType1 类型的异常
} catch (exceptionType2& e) {
    // 处理 exceptionType2 类型的异常
} catch (...) {
    // 处理所有其他类型的异常
}

示例

#include <iostream>
#include <exception>

class MyException : public std::exception {
public:
    const char* what() const noexcept override {
        return "Something bad happened!";
    }
};

void mayCauseException() {
    throw MyException(); // 抛出自定义异常
}

int main() {
    try {
        mayCauseException();
    } catch (const MyException& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Caught standard exception: " << e.what() << std::endl;
    } catch (...) {
        std::cerr << "Caught unknown exception" << std::endl;
    }
    return 0;
}

提高程序健壮性的建议

  • 合理设计异常类:根据程序可能出现的错误类型,设计合适的异常类层次结构。

  • 及时清理资源:在try块中分配的资源,在catch块中应该被正确释放,可以使用RAII(Resource Acquisition Is Initialization)技术。

  • 避免过度使用异常:异常应该用于处理真正的异常情况,而不是作为常规流程控制的一部分。

  • 使用标准异常类:尽可能使用C++标准库提供的异常类,如std::exception、std::runtime_error等。

  • 异常安全:确保异常抛出时,程序的状态是安全的,不会导致资源泄露或数据损坏。

通过上述方法,可以有效地利用C++的异常处理机制来提高程序的健壮性和可靠性。

智能指针

在C++中,智能指针是一种用于自动管理动态分配内存的工具,它们可以帮助避免内存泄漏并提高资源管理的安全性。C++11引入了三种主要的智能指针:unique_ptr、shared_ptr和weak_ptr。

unique_ptr

unique_ptr是一个独占所有权的智能指针,它确保同一时间只有一个unique_ptr指向一个对象。当unique_ptr离开作用域或被重新赋值时,它所指向的对象会被自动删除。

#include <iostream>
#include <memory>

int main() {
    // 创建一个 unique_ptr
    std::unique_ptr<int> uptr(new int(42));
    // 不能直接复制 unique_ptr
    // std::unique_ptr<int> uptr2 = uptr; // 错误

    // 可以通过移动语义转移所有权
    std::unique_ptr<int> uptr2 = std::move(uptr);
    if (!uptr) {
        std::cout << "uptr is empty" << std::endl;
    }
    std::cout << "uptr2 points to " << *uptr2 << std::endl;

    return 0;
}

shared_ptr

shared_ptr是一个共享所有权的智能指针,它允许多个shared_ptr指向同一个对象。对象的生命周期由引用计数管理,当最后一个指向对象的shared_ptr被销毁时,对象会被删除。

#include <iostream>
#include <memory>

int main() {
    // 创建一个 shared_ptr
    std::shared_ptr<int> sptr1(new int(42));
    std::cout << "sptr1 use count: " << sptr1.use_count() << std::endl; // 输出 1

    {
        std::shared_ptr<int> sptr2 = sptr1;
        std::cout << "sptr2 use count: " << sptr2.use_count() << std::endl; // 输出 2
    }

    std::cout << "sptr1 use count after sptr2 goes out of scope: " << sptr1.use_count() << std::endl; // 输出 1

    return 0;
}

weak_ptr

weak_ptr是一个弱引用智能指针,它通常与shared_ptr一起使用,用于解决循环引用的问题。weak_ptr不控制对象的生命周期,它只是观察shared_ptr所指向的对象。

#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> sptr(new int(42));
    std::weak_ptr<int> wptr(sptr);

    if (auto ptr = wptr.lock()) {
        std::cout << "Object is still alive, value: " << *ptr << std::endl;
    } else {
        std::cout << "Object is dead" << std::endl;
    }

    sptr.reset();

    if (auto ptr = wptr.lock()) {
        std::cout << "Object is still alive, value: " << *ptr << std::endl;
    } else {
        std::cout << "Object is dead" << std::endl;
    }

    return 0;
}

总结
智能指针是C++中管理动态内存的有效工具,它们可以自动处理内存的分配和释放,从而避免内存泄漏。unique_ptr适用于独占资源的情况,shared_ptr适用于共享资源的情况,而weak_ptr则用于解决shared_ptr可能导致的循环引用问题。合理使用这些智能指针可以显著提高C++程序的健壮性和安全性。

多线程编程

C++11引入了标准的多线程库,使得在C++中进行并发编程变得更加容易和安全。这个库包括了线程管理、互斥量、条件变量、原子操作和异步操作等功能。下面是一些主要组件的使用介绍:

std::thread

std::thread用于创建和管理线程。你可以通过它来启动一个新的线程,并执行一个函数。

#include <iostream>
#include <thread>

void threadFunction() {
    std::cout << "Hello from a thread!" << std::endl;
}

int main() {
    std::thread t(threadFunction);
    t.join(); // 等待线程结束
    return 0;
}

std::mutex

std::mutex是互斥量,用于保护共享资源,防止多个线程同时访问。

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void threadFunction() {
    mtx.lock();
    std::cout << "Hello from a thread!" << std::endl;
    mtx.unlock();
}

int main() {
    std::thread t1(threadFunction);
    std::thread t2(threadFunction);
    t1.join();
    t2.join();
    return 0;
}

std::lock_guard 和 std::unique_lock

std::lock_guard和std::unique_lock是互斥量的RAII风格的包装,它们在构造时自动锁定互斥量,在析构时自动解锁,确保了互斥量的正确管理。

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void threadFunction() {
    std::lock_guard<std::mutex> lock(mtx);
    std::cout << "Hello from a thread!" << std::endl;
}

int main() {
    std::thread t1(threadFunction);
    std::thread t2(threadFunction);
    t1.join();
    t2.join();
    return 0;
}

std::future 和 std::promise

std::future和std::promise用于在线程之间传递结果。std::promise用于设置值,而std::future用于获取这个值。

#include <iostream>
#include <thread>
#include <future>

void setPromise(std::promise<int>&& prom) {
    prom.set_value(42);
}

int main() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();

    std::thread t(setPromise, std::move(prom));
    std::cout << "Result: " << fut.get() << std::endl;
    t.join();
    return 0;
}

std::async

std::async是一个便捷的函数,它启动一个异步任务,并返回一个std::future对象,你可以通过这个对象获取任务的结果。

#include <iostream>
#include <future>

int compute() {
    return 42;
}

int main() {
    std::future<int> fut = std::async(compute);
    std::cout << "Result: " << fut.get() << std::endl;
    return 0;
}

C++11及以后版本的多线程库提供了丰富的并发编程工具,包括线程管理、同步原语和异步操作等。合理使用这些工具可以编写出高效且安全的并发程序。在编写多线程代码时,应该注意避免数据竞争和死锁,确保线程间的同步和通信是正确和高效的。

  • 29
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值