整理的现代 C++ 6 大核心前置知识点详解。每一个知识点都配有可直接运行的完整 C++11/14 代码示例和关键逻辑注释

整理的现代 C++ 6 大核心前置知识点详解。每一个知识点都配有可直接运行的完整 C++11/14 代码示例和关键逻辑注释
整理的现代 C 6 大核心前置知识点详解。每一个知识点都配有可直接运行的完整 C11/14 代码示例和关键逻辑注释。1. RAII资源获取即初始化核心概念RAIIResource Acquisition Is Initialization是现代 C 管理资源内存、文件句柄、锁、网络 Socket 等的最核心思想构造时获取资源析构时自动释放资源。利用栈对象的生命周期绑定资源。即使中途抛出异常栈对象也会被自动析构即“栈展开”从而绝对保证不发生资源泄漏。完整代码示例#includeiostream#includefstream#includestring#includestdexcept// 自定义 RAII 文件包装类classFileHandler{private:std::ofstream file;public:// 构造函数获取资源打开文件explicitFileHandler(conststd::stringfilename){file.open(filename);if(!file.is_open()){throwstd::runtime_error(无法打开文件);}std::cout[RAII] 文件已成功打开。\n;}// 提供写数据接口voidwrite(conststd::stringtext){filetext\n;}// 析构函数释放资源关闭文件~FileHandler(){if(file.is_open()){file.close();std::cout[RAII] 析构函数自动触发文件已安全关闭。\n;}}};voidrunDemo(){FileHandlermyFile(test.txt);myFile.write(Hello, RAII!);// 假设这里发生业务逻辑处理...// 无论函数是正常返回还是中途抛出异常myFile 离开作用域时都会自动关闭文件}intmain(){runDemo();return0;}2.std::move与移动语义核心概念深拷贝Copy当把一个包含大块内存的对象赋值给另一个对象时默认需要重新申请一块新内存并逐字节复制开销大。移动Move直接把源对象的内部指针/资源所有权“偷”过来将源对象的指针置空开销极小仅相当于指针赋值。std::move它本身不移动任何东西只做强行类型转换——把一个左值有名字的对象转换为右值引用T告诉编译器“这个对象我不用了你可以窃取它的资源”。完整代码示例#includeiostream#includeutility#includecstringclassDynamicBuffer{public:int*data;size_t size;// 1. 普通构造函数explicitDynamicBuffer(size_t s):size(s),data(newint[s]){std::cout分配内存大小: size\n;}// 析构函数~DynamicBuffer(){delete[]data;}// 2. 拷贝构造函数深拷贝开销大DynamicBuffer(constDynamicBufferother):size(other.size),data(newint[other.size]){std::memcpy(data,other.data,size*sizeof(int));std::cout[深拷贝] 重新申请内存并复制数据\n;}// 3. 移动构造函数窃取资源开销小DynamicBuffer(DynamicBufferother)noexcept:data(other.data),size(other.size){// 剥夺原对象的资源所有权other.datanullptr;other.size0;std::cout[移动构造] 零开销接管原有内存\n;}};intmain(){DynamicBufferbuf1(100000);// buf1 持有大块内存std::cout--- 执行拷贝 ---\n;DynamicBuffer buf2buf1;// 调用拷贝构造函数std::cout--- 执行移动 ---\n;DynamicBuffer buf3std::move(buf1);// 将 buf1 转为右值触发移动构造函数std::coutbuf1 现在的指针状态: buf1.data (已被安全清空)\n;return0;}3. 智能指针std::unique_ptr与std::shared_ptr核心概念智能指针是 C 基于 RAII 实现的自动内存管理工具彻底替代裸指针new/delete。std::unique_ptr独占式所有权。同一时间只能有一个unique_ptr指向该对象。不能拷贝只能移动如std::thread的语义。std::shared_ptr共享式所有权。内部维护一个引用计数多处共享同一个对象。只有当最后一个shared_ptr被析构计数清零时才会真正销毁内存。完整代码示例#includeiostream#includememoryclassWidget{public:Widget(){std::coutWidget 构造\n;}~Widget(){std::coutWidget 析构\n;}voiddoWork(){std::coutWidget 正在工作...\n;}};voiddemoUniquePtr(){std::cout\n std::unique_ptr 演示 \n;// 推荐使用 std::make_unique (C14)std::unique_ptrWidgetp1std::make_uniqueWidget();// std::unique_ptrWidget p2 p1; // ❌ 编译报错无法拷贝// 所有权转移移动std::unique_ptrWidgetp2std::move(p1);if(!p1){std::coutp1 已失去所有权变成空指针。\n;}p2-doWork();}// 离开作用域p2 自动析构并 delete WidgetvoiddemoSharedPtr(){std::cout\n std::shared_ptr 演示 \n;std::shared_ptrWidgetsp1std::make_sharedWidget();std::cout当前引用计数: sp1.use_count()\n;// 1{std::shared_ptrWidgetsp2sp1;// 允许拷贝计数 1std::cout拷贝后引用计数: sp1.use_count()\n;// 2}// sp2 离开作用域计数 -1std::cout局部变量析构后引用计数: sp1.use_count()\n;// 1}// 离开作用域计数变为 0自动 delete Widgetintmain(){demoUniquePtr();demoSharedPtr();return0;}4. Lambda 表达式核心概念Lambda 是 C11 引入的匿名函数闭包。在多线程开发中常用它作为线程std::thread的入口函数或回调。语法规范[捕获列表](参数列表) - 返回类型 { 函数体 }**值捕获[x]**在 Lambda 创建时拷贝变量副本。**引用捕获[x]**直接引用外部变量多线程中使用引用捕获要注意变量生命周期防止悬空引用。**全捕获[]/[]**隐式按值 / 按引用捕获所有外部局部变量。完整代码示例#includeiostream#includevector#includealgorithmintmain(){intfactor3;intsum0;std::vectorintnums{1,2,3,4,5};// 1. 混合捕获factor 按值捕获sum 按引用捕获std::for_each(nums.begin(),nums.end(),[factor,sum](intn){intresultn*factor;sumresult;std::coutn * factor result\n;});std::cout计算总和为: sum\n;// 2. 带返回值的 Lambdaautoadd[](inta,intb)-int{returnab;};std::cout10 20 add(10,20)\n;return0;}5.std::function与std::bind核心概念std::functionR(Args...)通用可调用对象包装器。它可以存放普通函数、Lambda 表达式、成员函数、函数对象Functor。它是实现灵活回调函数的核心机制。std::bind用于把可调用对象的部分参数进行绑定预置参数或者调整参数顺序生成一个新的可调用对象。注现代 C 中大多数场景建议优先使用 Lambda 替代std::bind但读旧代码或结合std::function时依然很常见。完整代码示例#includeiostream#includefunctional// 1. 普通函数voidprintSum(inta,intb){std::cout普通函数计算: ab\n;}// 2. 包含成员函数的类classCalculator{public:voidmultiply(inta,intb){std::cout类成员函数计算: a*b\n;}};intmain(){// ---- std::function 统一包装 ----// 包装普通函数std::functionvoid(int,int)funcprintSum;func(3,4);// 包装 Lambda 表达式func[](inta,intb){std::coutLambda 计算: a-b\n;};func(10,4);// ---- std::bind 绑定参数与成员函数 ----Calculator calc;// 绑定类成员函数必须传入类对象指针/引用作为第一个隐含参数autoboundMemberFuncstd::bind(Calculator::multiply,calc,std::placeholders::_1,std::placeholders::_2);boundMemberFunc(5,6);// 绑定固定参数将第一个参数固定为 100使用 std::placeholders::_1 作为新的第一个参数autoadd100std::bind(printSum,100,std::placeholders::_1);add100(50);// 相当于调用 printSum(100, 50)return0;}6. 模板基础函数模板与类模板核心概念模板是 C泛型编程的基础。通过将数据类型本身“参数化”实现一套代码适配多种数据类型函数模板根据调用时传入的具体参数类型编译器在编译期自动生成对应类型的具体函数。类模板如std::vectorT、std::atomicT、std::lock_guardMutex可以处理不同类型的类定义。完整代码示例#includeiostream#includestring// 1. 函数模板通用获取最大值templatetypenameTTgetMax(T a,T b){return(ab)?a:b;}// 2. 类模板通用数据容器templatetypenameTclassSafeContainer{private:T element;public:explicitSafeContainer(T val):element(val){}TgetValue()const{returnelement;}voidprint()const{std::cout容器内存储的值: element\n;}};intmain(){// ---- 函数模板测试 ----std::coutint 最大值: getMax(10,20)\n;// 自动推导为 intstd::coutdouble 最大值: getMax(3.14,2.71)\n;// 自动推导为 doublestd::coutstring 最大值: getMax(std::string(Apple),std::string(Banana))\n;// ---- 类模板测试 ----SafeContainerintintContainer(123);intContainer.print();SafeContainerstd::stringstrContainer(Concurrency);strContainer.print();return0;}学习与复习建议把上面的 6 段代码分别复制到 Visual Studio 2022 中运行一遍。重点感受 **std::unique_ptr只能被std::move**的特性因为后续学习std::thread时std::thread也是完全遵循同样的“不能拷贝、只能移动”的规则

最新新闻

日新闻

周新闻

月新闻