目录
1、简介
2.自动类型推导和初始化
示例代码
3.智能指针
示例代码
4.Lambda 表达式
示例代码
5.右值引用和移动语义
示例代码
6.并发编程支持
示例代码
7.其他特性
八、案例:实现一个简单的并发下载器
上一篇文章:
C++标准模板库(STL)是C++的一个重要组成部分,它提供了一套丰富的通用数据结构和算法。STL以其高度模块化、可复用的特性,在C++编程中发挥着重要作用。本篇博客将带你深入了解STL,并介绍其常见的组件和使用方法。
C++学习笔记——标准模板库-CSDN博客C++标准模板库(STL)是C++的一个重要组成部分,它提供了一套丰富的通用数据结构和算法。STL以其高度模块化、可复用的特性,在C++编程中发挥着重要作用。本篇博客将带你深入了解STL,并介绍其常见的组件和使用方法。C++标准模板库(STL)是C++语言的一个标准库,它提供了一套通用的数据结构和算法,以支持高效的编程。STL的设计目标是使程序员能够以简洁、高效和可复用的方式开发代码。// 输出vector的大小return 0;https://blog.csdn.net/m0_62338174/article/details/135573281?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22135573281%22%2C%22source%22%3A%22m0_62338174%22%7D
C++ 是一种功能强大的编程语言,它一直在不断发展和演进。自从 C++11 标准发布以来,C++ 引入了许多重要的新特性,如智能指针、Lambda 表达式、右值引用等。随后的 C++14 和 C++17 标准也带来了更多的改进和增强。本篇博客将详细介绍 C++ 新标准引入的一些重要特性,并给出代码示例和详细解释,帮助读者了解和应用这些特性。
C++11 引入了 auto 关键字和统一的初始化语法,使得变量的类型推导更加方便。在 C++11 之前,我们必须手动指定变量的类型,例如 int、double 等。但是在某些情况下,类型可能比较复杂或者难以确定,使用 auto 关键字可以自动推导出变量的类型。同时,C++11 还引入了统一的初始化语法,允许我们使用初始化列表对变量进行初始化,这样代码更加简洁和易读。
auto x = 10; // x 的类型被推导为 int
auto y = 3.14; // y 的类型被推导为 double
std::vector nums = {1, 2, 3}; // 使用初始化列表进行初始化
C++11 引入了智能指针,用于管理动态分配的内存,避免内存泄漏和悬空指针的问题。其中最常用的是 shared_ptr 和 unique_ptr。shared_ptr 允许多个指针共享同一个对象,并且会自动进行内存回收,直到所有指针都不再需要该对象。unique_ptr 则保证每个对象只有一个指针拥有它,可以通过 std::move 函数实现所有权的转移。
std::shared_ptr p1 = std::make_shared(10); // 使用 make_shared 创建 shared_ptr
std::unique_ptr p2(new int(20)); // 使用 new 创建 unique_ptr
if (p1) {
std::cout << *p1 << std::endl; // 访问指针指向的值
}
C++11 引入了 Lambda 表达式,允许我们在代码中定义匿名函数,简化了函数对象的使用和编写。Lambda 表达式的基本形式为 [ capture-list ] ( params ) mutable exception -> return-type { body },其中 capture-list 表示变量捕获列表,params 表示参数列表,mutable 和 exception 表示是否可变和异常规范,return-type 表示返回类型,body 表示函数体。
std::vector nums = {1, 2, 3, 4, 5};
// 使用 Lambda 表达式对容器进行遍历和操作
std::for_each(nums.begin(), nums.end(), [](int n) {
std::cout << n * 2 << " ";
});
C++11 引入了右值引用和移动语义,通过 std::move 函数实现对资源的高效转移,提高了性能和效率。右值引用用 && 表示,可以绑定到临时对象、表达式、返回右值引用的函数等,允许我们对这些对象进行高效的转移和管理。移动语义则是指通过右值引用实现资源的转移,避免了复制和销毁的开销。
std::string str = "Hello";
std::vector vec;
vec.push_back(std::move(str)); // 使用 std::move 转移资源
std::cout << str << std::endl; // 输出为空,str 的资源已被转移
C++11 引入了一套完整的并发编程库,包括原子操作、线程、互斥量、条件变量等,方便开发者进行多线程编程和并发控制。其中最常用的就是 std::thread 类和 std::mutex 类。std::thread 可以创建新的线程,并执行指定的函数或 Lambda 表达式,std::mutex 则可以保护共享资源,避免多个线程同时访问和修改同一个变量。
std::mutex mtx;
int count = 0;
std::vector threads;
for (int i = 0; i < 10; ++i) {
threads.emplace_back([&]() {
std::lock_guard lock(mtx); // 使用互斥量保护共享资源
count++;
});
}
for (auto& thread : threads) {
thread.join();
}
std::cout << "count: " << count << std::endl;
C++14 和 C++17 标准引入了更多的改进和增强,如通用 lambda、变长模板、constexpr 函数、初始化列表等。通用 lambda 允许我们对任意类型的参数进行操作,变长模板则可以支持任意数量和任意类型的模板参数,constexpr 函数可以在编译时计算结果,初始化列表则可以方便地对复杂对象进行初始化。
#include
#include
#include
#include
std::mutex mtx;
void downloadFile(const std::string& url, const std::string& filename) {
// 模拟下载文件的耗时操作
std::this_thread::sleep_for(std::chrono::seconds(2));
// 使用互斥量保护共享资源
std::lock_guard lock(mtx);
std::cout << "Downloaded file: " << url << " saved as: " << filename << std::endl;
}
int main() {
std::vector urls = {
"http://example.com/file1.txt",
"http://example.com/file2.txt",
"http://example.com/file3.txt"
};
std::vector threads;
for (const auto& url : urls) {
threads.emplace_back([&]() {
// 生成文件名
std::string filename = "file_" + std::to_string(std::hash()(url)) + ".txt";
downloadFile(url, filename);
});
}
for (auto& thread : threads) {
thread.join();
}
return 0;
}
具体而言,程序首先定义了一个包含多个 URL 的 std::vector 对象 urls,这些 URL 表示需要下载的文件地址。然后我们创建了一个 std::vector 对象 threads,用于存储多个线程对象。接着我们使用 for 循环遍历 urls,每次循环都会创建一个新的线程,并将其加入到 threads 中。每个线程都会调用 downloadFile 函数进行文件下载,同时生成一个唯一的文件名。
downloadFile 函数模拟了文件下载的耗时操作,具体而言,我们使用了 std::this_thread::sleep_for 函数,让线程休眠 2 秒钟,模拟文件下载的过程。在函数结束之前,我们使用 std::lock_guardstd::mutex 对共享资源进行了保护,确保每个线程都能够正确地输出下载完成的信息。
以上是一个简单的并发下载器示例。我们使用了 C++11 的并发编程支持,通过创建多个线程并发地下载多个文件。每个线程都会调用 downloadFile 函数进行文件下载,而该函数会使用互斥量保护共享资源,避免多个线程同时访问和修改同一个文件。
通过这个案例,我们可以看到 C++11 的并发编程支持非常强大,可以方便地实现多线程的应用程序,提高程序的性能和效率。同时,使用互斥量等工具可以保证多线程的安全性,避免竞态条件和数据竞争的问题。