当前位置: 首页 > news >正文

C++11新特性深度解析

目录

一、统一的初始化语法

1.1 基本使用示例

1.2 对象初始化

二、initializer_list容器

2.1 标准容器支持

2.2 自定义容器实现​编辑

三、类型推导与decltype

3.1 auto关键字

3.2 decltype类型推导

四、nullptr替代NULL

五、array容器

六、右值引用与移动语义

6.1 左右值概念 

6.2 移动构造函数与移动赋值

6.3 push_back 的拷贝与移动

6.4 完美转发

6.4.1左值引用与右值引用

6.4.2 万能引用与引用折叠

七、 Lambda 表达式与排序

7.1 传统仿函数 vs. Lambda

7.2 Lambda 的灵活应用

八、可变参数模板

8.1 基本概念

示例:递归展开参数包

8.2. 可变参数模板的应用

8.2.1 灵活构造对象

8.2.2 emplace_back vs. push_back

8.3 移动语义的默认行为

8.3.1 默认生成的移动操作

九、 包装器 (function)

9.1示例:统计调用次数

9.2使用 std::function 优化

十、 参数绑定(bind)

10.1 调整参数顺序与固定参数

10.2 绑定成员函数

10.3 实现多策略计算器


一、统一的初始化语法

C++11引入了统一初始化语法,允许使用花括号{}进行各种初始化操作,使代码更加一致和清晰。

1.1 基本使用示例

int x = 1;       // 传统初始化
int y = {2};     // 使用初始化列表
int z{3};        // 直接列表初始化int a1[] = {1,2,3};  // 传统数组初始化
int a2[] {1,2,3};    // 列表初始化数组

1.2 对象初始化

struct Point {Point(int x, int y) : _x(x), _y(y) {cout << "Point构造" << endl;}int _x, _y;
};Point p0(0, 0);         // 传统构造
Point p1 = {1,1};       // 隐式类型转换
Point p2{2,2};          // 直接列表初始化
const Point& r = {3,3}; // 临时对象绑定到const引用

二、initializer_list容器

C++11引入了initializer_list类型,支持使用初始化列表构造容器。

2.1 标准容器支持

vector<int> v1 = {1,2,3,4,5};  // 调用initializer_list构造函数
map<string, string> dict = { {"sort", "排序"}, {"left", "左边"} 
};

2.2 自定义容器实现

// 自定义vector添加initializer_list支持
template<class T>
class vector {
public:vector(initializer_list<T> il) {reserve(il.size());for(auto& e : il) {push_back(e);}}// ...
};

三、类型推导与decltype

3.1 auto关键字

auto i = 10;          // int
auto p = &i;          // int*
auto pf = malloc;     // void*(*)(size_t)
vector<int> v;
auto it = v.begin();  // vector<int>::iterator

3.2 decltype类型推导

int x = 1;
double y = 2.2;decltype(x) a;        // int
decltype(x*y) b;      // double
decltype(pf) pf2;     // 与pf相同类型template<class Func>
class B {Func _f;          // 使用decltype作为模板参数
};
B<decltype(pf)> bb1;  // 实例化模板

四、nullptr替代NULL

C++11引入nullptr解决NULL的二义性问题:

NULL是宏定义的0

找不到nullptr的宏定义,但是从下图知道,nullptr是(void*) 0

void func(int) {}
void func(int*) {}int main() {func(NULL);    // 调用func(int)func(nullptr); // 调用func(int*)return 0;
}

五、array容器

C++11提供了更安全的固定大小数组替代品:

区别就是有无报错

int a1[10];              // 传统C数组
array<int,10> a2;        // C++11 array容器cout << sizeof(a1) << endl;  // 40 (假设int为4字节)
cout << sizeof(a2) << endl;  // 40a1[15] = 1;  // 未定义行为
a2[15] = 1;  // 运行时抛出异常(调试模式下)

六、右值引用与移动语义

6.1 左右值概念 

左值(Lvalue):有名字、可寻址的对象(如变量、数组元素)。

右值(Rvalue):临时对象、字面量、表达式结果(如 10x + y)。

我的理解:能取地址的是左值,不能取地址的是右值

int a = 10;          // a是左值
int* p = &a;         // 可以取地址
10;                  // 右值
a + 10;              // 右值
fmin(a, 10);         // 右值

6.2 移动构造函数与移动赋值

移动语义通过“窃取”资源(如动态内存)来优化性能。

示例代码(string 类)

string(string&& s) : _str(nullptr) {cout << "移动构造" << endl;swap(s);  // 直接交换资源,避免深拷贝
}string& operator=(string&& s) {cout << "移动赋值" << endl;swap(s);return *this;
}

6.3 push_back 的拷贝与移动

list<bit::string> lt;
bit::string s1("111111111111111111111");
lt.push_back(s1);  // 调用拷贝构造bit::string s2("111111111111111111111");
lt.push_back(move(s2));  // 调用移动构造lt.push_back("22222222222222222222222222222");  // 直接构造(最优)

说明

push_back(s1) 触发拷贝构造(深拷贝)

push_back(move(s2)) 触发移动构造(资源转移)

push_back("...") 直接构造(最优化,避免临时对象)

6.4 完美转发

6.4.1左值引用与右值引用
	double x = 1.1, y = 2.2;// 左值引用:给左值取别名int a = 0;int& r1 = a;// 左值引用能否给右值取别名?// const左值引用可以const int& r2 = 10;const double& r3 = x + y;// 右值引用:给右值取别名int&& r5 = 10;double&& r6 = x + y;// 右值引用能否给左值取别名?// 右值引用可以引用move以后的左值int&& r7 = move(a);
6.4.2 万能引用与引用折叠
template<typename T>
void PerfectForward(T&& t) {Fun(forward<T>(t));  // 保持左值/右值属性
}

示例调用

PerfectForward(10);           // 右值引用
int a;
PerfectForward(a);            // 左值引用
PerfectForward(move(a));      // 右值引用
const int b = 8;
PerfectForward(b);            // const 左值引用
PerfectForward(move(b));      // const 右值引用

​​​​T&& 是万能引用,根据实参推导左值/右值

std::forward<T> 保持参数的原始类型(避免不必要的拷贝)

七、 Lambda 表达式与排序

7.1 传统仿函数 vs. Lambda

// 传统仿函数
struct ComparePriceLess {bool operator()(const Goods& x, const Goods& y) {return x._price < y._price;}
};
sort(v.begin(), v.end(), ComparePriceLess());// Lambda 表达式
sort(v.begin(), v.end(), [](const Goods& x, const Goods& y) {return x._price < y._price;
});

7.2 Lambda 的灵活应用

vector<Goods> v = { {"苹果", 2.1, 5}, {"香蕉", 3, 4}, {"橙子", 2.2, 3} };// 按价格升序
sort(v.begin(), v.end(), [](auto& x, auto& y) { return x._price < y._price; });// 按评价降序
sort(v.begin(), v.end(), [](auto& x, auto& y) { return x._evaluate > y._evaluate; });

八、可变参数模板

8.1 基本概念

可变参数模板允许函数/类接受任意数量、任意类型的参数包

示例:递归展开参数包
void _ShowList() { cout << endl; }  // 终止条件template <class T, class... Args>
void _ShowList(T val, Args... args) {cout << val << " ";_ShowList(args...);  // 递归调用
}template <class... Args>
void CppPrint(Args... args) {_ShowList(args...);
}int main() {CppPrint(1, 2.2, "hello");  // 输出:1 2.2 helloreturn 0;
}

示例:数组展开参数包

template <class T>
int PrintArg(T t) {cout << t << " ";return 0;
}template <class... Args>
void CppPrint(Args... args) {int arr[] = { PrintArg(args)... };  // 展开为 {PrintArg(1), PrintArg(2.2), ...}cout << endl;
}

8.2. 可变参数模板的应用

8.2.1 灵活构造对象
template <class... Args>
Date* Create(Args... args) {return new Date(args...);  // 直接传递参数包构造对象
}int main() {Date* p1 = Create();           // 默认构造Date* p2 = Create(2023, 9, 27); // 多参数构造return 0;
}
8.2.2 emplace_back vs. push_back
std::list<std::pair<int, string>> mylist;
mylist.emplace_back(10, "sort");  // 直接构造,无拷贝
mylist.push_back({20, "left"});   // 构造临时对象 + 移动构造

8.3 移动语义的默认行为

8.3.1 默认生成的移动操作
class Person {
public:Person(Person&&) = default;  // 默认移动构造Person(const Person&) = default;  // 默认拷贝构造
private:bit::string _name;int _age;
};int main() {Person s1;Person s2 = s1;       // 拷贝构造Person s3 = move(s1); // 移动构造return 0;
}

如果你没有自己实现移动构造函数,且没有实现析构函数、铐贝构造、铐贝赋值重载中的任意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,如果实现了就调用移动构造,没有实现就调用拷贝构造。

九、 包装器 (function)

std::function 可以包装函数指针、仿函数、Lambda 等,提供统一的调用接口。

9.1示例:统计调用次数
template<class F, class T>
T useF(F f, T x) {static int count = 0;cout << "count:" << ++count << endl;return f(x);
}int main() {// 函数指针cout << useF(f, 11.11) << endl;  // count:1// 仿函数cout << useF(Functor(), 11.11) << endl;  // count:1(不同实例)// Lambdacout << useF([](double d) { return d/4; }, 11.11) << endl;  // count:1return 0;
}

问题:模板实例化导致多次计数(不同调用类型生成不同 useF 实例)。

9.2使用 std::function 优化
#include <functional>double useF(std::function<double(double)> f, double x) {static int count = 0;cout << "count:" << ++count << endl;return f(x);
}int main() {// 统一类型,共享静态变量useF(f, 11.11);          // 函数指针useF(Functor(), 11.11);  // 仿函数useF([](double d) { return d/4; }, 11.11);  // Lambdareturn 0;
}

十、 参数绑定(bind)

10.1 调整参数顺序与固定参数

int Sub(int a, int b) { return a - b; }int main() {// 绑定参数顺序:原函数Sub(a,b) -> 新函数Sub(b,a)auto reversedSub = bind(Sub, placeholders::_2, placeholders::_1);cout << reversedSub(10, 5) << endl;  // 输出-5(即5-10)// 固定部分参数auto subFrom100 = bind(Sub, 100, placeholders::_1);cout << subFrom100(30) << endl;  // 输出70(100-30)return 0;
}

10.2 绑定成员函数

class Calculator {
public:static int Add(int a, int b) { return a + b; }int Multiply(int a, int b) { return a * b; }
};int main() {// 绑定静态成员函数auto add = bind(&Calculator::Add, placeholders::_1, placeholders::_2);cout << add(3, 4) << endl;  // 输出7// 绑定普通成员函数(需对象实例)Calculator calc;auto multiply = bind(&Calculator::Multiply, &calc, placeholders::_1, placeholders::_2);cout << multiply(3, 4) << endl;  // 输出12return 0;
}

10.3 实现多策略计算器

class MathProcessor {vector<function<double(double, double)>> operations;
public:void addOperation(function<double(double, double)> op) {operations.push_back(op);}void process(double x, double y) {for (auto& op : operations) {cout << "Result: " << op(x, y) << endl;}}
};int main() {MathProcessor processor;// 添加不同操作processor.addOperation([](double a, double b) { return a + b; });processor.addOperation(bind(Sub, placeholders::_1, placeholders::_2));processor.addOperation(bind(PPlus, placeholders::_1, 1.5, placeholders::_2));processor.process(10.0, 5.0);/* 输出:Result: 15Result: 5Result: 22.5*/return 0;
}

http://www.dtcms.com/a/331434.html

相关文章:

  • Linux软件下载菜单脚本
  • Effective C++ 条款41:理解隐式接口和编译期多态
  • 系统设计——DDD领域模型驱动实践
  • 深入浅出词向量(Word2Vec):从理论到实践
  • 数据结构初阶(13)排序算法-选择排序(选择排序、堆排序)(动图演示)
  • 【Java 后端】Spring Boot 集成 JPA 全攻略
  • HTTPS 工作原理
  • 电池充放电测试仪厂家:技术深耕与场景驱动的行业进阶
  • Java使用Apache POI读取Excel文件
  • Vue浅学
  • 深入解析 GitHub Actions 工作流文件编写:从入门到实战
  • 简单的 HTTPS 学习
  • 第四天-创建一个Classic CAN(经典CAN2.0)/CANFD的系统描述ARXML文件
  • 读From GPT-2 to gpt-oss: Analyzing the Architectural Advances
  • IPv6互联网地址解析
  • 从合规到卓越:全星QMS如何成为制造企业的质量战略引擎
  • linux 软硬链接详解
  • 《算法导论》第 25 章:所有结点对的最短路径问题
  • 计算机视觉CS231n学习(8)
  • 12 ABP Framework 租户管理
  • 介绍一下 自动驾驶 感知多任务训练模型设计
  • 面试题:如何用Flink实时计算QPS
  • 第4节 神经网络从公式简化到卷积神经网络(CNN)的进化之路
  • 第三章、GRU(门控循环网络,Gated Recurrent Unit)
  • redis中分布式锁的应用
  • 【js】让项目支持倾听和朗读AI技术
  • RTC时钟倒计时数码管同步显示实现(STC8)
  • AI模型选型:租快艇还是造航母?
  • 协作同步问题的深度分析与解决方案:结合表单汇总与AI技术提升运维效能
  • Git报错:Unlink of file ‘src/global/env.ts‘ failed. Should I try again? (y/n) y