c++新特性(序列for循环,Lambda,委托构造和继承构造)
·
引言
c++11引用非常多的新的编程规范和语法我们进行看一下。
序列for循环:
简化代码,语法简洁且能避免数组越界,遍历普通数组和stl容器。
#include<iostream>
#include<vector>
using namespace std;
int main(){
//正常for循环
vector<int>a={2,234,23423,4,2,5,6,23};
for(int i=0;i<a.size();i++){
cout<<a[i]<<endl;
}
//序列for循环
for(auto x:a){
cout<<x<<endl;
}
return 0;
}
缺点:无法跳过某个位置。
Lambda表达式(匿名函数):
可以在需要的时候定义一个临时函数,无需声明,一般试用与stl算法的参数,qt后面的信号与槽用到,让代码更紧凑。
语法:[captyre list](parameter list) mutable exception->return type{function body}
[捕获列表](参数列表) mutable修饰符 异常说明->尾置返回类型{函数体}
| 名称 | 作用 | 案例 |
| 捕获列表 | 定义 Lambda 表达式能否 / 如何访问其所在 “外部作用域” 的变量(如外部函数的局部变量、全局变量等)。 | [=]:捕获外部全部变量 [&x,y]:引用捕获变量x,值变量捕获y |
| 参数列表 | 与普通函数的参数列表一致 | (int a, double b) |
| mutable修饰符 | 默认情况下,Lambda 若 “值捕获” 外部变量,不允许修改这些变量;添加mutable后,允许在 Lambda 内部修改值捕获的变量(仅修改副本,不影响外部原变量)。 | |
| 异常说明 | 声明 Lambda 表达式是否可能抛出异常,以及抛出哪些类型的异常(C++11 后常用noexcept表示 “不抛出任何异常”)。 | noexcept(声明此 Lambda 不会抛出任何异常)、throw(int, double)(声明可能抛出 int 或 double 类型的异常,C++17 后逐渐被noexcept替代)。 |
| 返回类型 | 显式指定 Lambda 表达式的返回值类型。若 Lambda 体内只有一条return语句,编译器可自动推导返回类型,此时可省略该部分;若有多条return语句或需明确类型,需显式声明。 | ->int(声明返回值为 int 类型)、->vector<string>(声明返回值为vector<string>类型)。 |
| 函数体 | Lambda 表达式的 “执行逻辑”,与普通函数的函数体一致,包含具体的代码语句 | { return a + b; } |
算法参数:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//正常操作
bool comparefunc(int a,int b){
return a>b;}
int main(){
vector<int> v1={2,6,1,7,8,9,0,4,5};
sort(v1.begin(),v1.end(),comparefunc);
for(auto i:v1){
cout<<i<<endl;}
vector<int> v2={2,6,1,7,8,9,0,4,9,5};
//lambda表达式
sort(v2.begin(),v2.end(),[](int a,int b) ->bool{return a>b});
for(auto i:21){
cout<<i<<endl;}
return 0;
}
委托构造和继承构造:
委托构造函数:
允许同一个类中的构造函数调用另一个构造函数。
作用:
- 避免多个构造函数中重复编写相同的初始化代码;
- 将初始化逻辑集中到一个 “基础构造函数” 中,其他构造函数通过委托复用该逻辑,仅处理自己的特殊参数。
#include<iostream>
using namespace std;
class MyClass{
private:
int x;
double y;
public:
//普通构造函数
MyClass(int a,int b){
x=a;
y=b;
cout<<"普通构造函数"<<endl;}
MyClass(int x):MyClass(x,0.0){
cout<<"委托构造函数一个参数的";
}
MyClass():MyClass(0,0.0){
cout<<"委托构造函数无参"<<endl;
}
};
int main(){
MyClass obj(20,20.6);
MyClass obj1;
MyClass obj2(33);
return 0;
}
继承构造函数:
派生类继承基类的构造函数
作用:
- 当派生类不需要修改基类构造函数的逻辑,仅需 “复用基类的构造函数来初始化基类部分成员” 时,避免重复定义;
- 尤其适合基类有多个构造函数的场景(如基类有 5 个构造函数,派生类无需逐个重写)
语法:
通过 using 基类名::基类构造函数名(通常直接写 using Base::Base;)在派生类中声明继承基类的所有构造函数:
#include<iostreaam>
using namespace std;
// 基类
class Base {
private:
int x;
public:
Base() : x(0) {}
Base(int a) : x(a) {}
Base(int a, double b) : x(a) {} // 基类有3个构造函数
};
// 派生类
class Derived : public Base {
private:
int y; // 派生类新增成员
public:
// 继承基类的所有构造函数
using Base::Base; // 关键:声明继承基类构造函数
// 派生类自己的构造函数(若需要)
Derived(int a, int b) : Base(a), y(b) {} // 同时初始化基类和派生类成员
};
int main(){
Derived d1; // 调用继承的 Base() 构造函数(初始化基类x)
Derived d2(5); // 调用继承的 Base(int a) 构造函数
Derived d3(3, 4.5);// 调用继承的 Base(int a, double b) 构造函数
Derived d4(2, 3); // 调用派生类自己的构造函数
return 0;}
总结:
- 普通构造函数是基础,负责类成员的直接初始化;
- 委托构造函数是 “同类内的复用工具”,通过调用同类其他构造函数减少重复代码;
- 继承构造函数是 “跨类(派生类与基类)的复用工具”,让派生类无需重写基类已有的构造函数。
垃圾回收机制:
c++里面没有垃圾回收机制,一般用于手动管理和确定性资源释放(rall)(智能指针,标准容器);
下面介绍在计算机科学方面4中垃圾回收机制:
| 算法名称 | 核心思想 | 主要优点 | 主要缺点 | 典型应用场景 |
|---|---|---|---|---|
| 引用计数算法 | 为每个对象维护引用计数器,计数为 0 时立即回收 | 1. 垃圾产生后立即回收(实时性好)2. 实现逻辑简单 | 1. 无法解决循环引用(如 A 引用 B,B 引用 A)2. 每次引用操作需更新计数,有额外时间开销3. 每个对象需额外存储计数字段,占用空间 | C++ std::shared_ptr、Python(部分对象) |
| 标记 - 清除算法 | 1. 标记:从根对象出发标记所有可达对象2. 清除:回收未被标记的对象 | 1. 可解决循环引用问题2. 适用于任意类型垃圾回收 | 1. 需暂停程序(STW),影响实时性2. 回收后产生内存碎片3. 需遍历所有对象,效率随内存增大下降 | 早期 Java GC、Boehm GC(C++ 第三方库) |
| 分代回收算法 | 按对象存活时间分为多代(如年轻代、老年代),不同代采用不同策略回收 | 1. 针对 “多数对象存活时间短” 的特性优化,效率高2. 年轻代高频回收成本低,减少整体 STW 时间 | 1. 实现复杂(需维护分代逻辑和对象晋升规则)2. 老年代全量回收时仍可能有较长停顿 | Java(G1、ZGC)、C# 垃圾回收 |
| 复制算法(节点拷贝算法) | 将内存分为两块,仅使用一块;回收时复制存活对象到另一块,清空原块 | 1. 回收后内存无碎片(存活对象紧凑排列)2. 回收效率高(仅处理存活对象) | 1. 空间利用率低(始终有一半内存空闲)2. 存活对象多时,复制操作成本高 | 分代回收中的年轻代(如 Java 年轻代的 Eden 区与 Survivor 区) |
总结:
序列for循环用于遍历数组和stl容器
lambda表达式用于算法函数参数的使用,起到简化代码的。
委托构造和继承构造都是为了减少重复代码,提高代码的复用性。
上面的基本都是用与简化代码的。
更多推荐



所有评论(0)