C++11的内容

1.支持花括号初始化

void test1()
{vector<string> v1 = { "asd","asd","add" };vector<string> v2{ "asd","asd","add" };map<string, int> m1={ {"asd",1},{"asd",2},{"asd",3} };map<string, int> m2{ {"asd",1},{"asd",2},{"asd",3} };}

当编译器遇到花括号初始化表达式时,会发生以下的步骤:

template<class T>
class F
{
public:F(std::initializer_list<T> il) {};     //  如果该构造函数存在直接就调用F() {};
};

步骤 1:

优先匹配 std::initializer_list 构造函数 如果类型 F定义了 接受 std::initializer_list的构造函数 (如 F(std::initializer_list<U>)),编译器会优先尝试调用它。 此时,花括号内的所有参数会被打包成一个 std::initializer_list<T>临时对象,其中 T 是花括号内元素的统一类型(需支持隐式转换)。

步骤2:

 如果 initializer_list构造函数不匹配(如参数类型无法转换,或未定义该构造函数),编译器会按常规构造函数重载决议规则选择其他构造函数。 花括号内的参数会逐个传递给构造函数,如同圆括号初始化。

步骤3:

聚合类型的直接初始化 如果T是聚合类型(如没有用户自定义构造函数的结构体、数组等),花括号会按声明顺序直接初始化成员。

template<class T>
class F
{
public://F(std::initializer_list<T> il) {};     //  如果该构造函数存在直接就调用//F() {};int _a;double _b;
};void test()
{F<int> f{ 1,1.0 };  // 按声明顺序初始化
}

注意:

1.窄化转换的检查 无论调用哪种构造函数,花括号初始化都会静态检查窄化转换(如 double→int),若存在则编译失败。

template<class T>
class F
{
public://F(std::initializer_list<T> il) {};     //  如果该构造函数存在直接就调用//F() {};int _a;double _b;
};void test()
{F<int> f{ 1.1,1.0 };  // 按声明顺序初始化  // double->int 本应该发生窄化报错,但发生了自定义类型的隐式类型的转化int x{ 1.5 };  //  编译时报错
}

2.当默认构造函数和initlalizer_list都存在时,花括号里面非空,调用initializer_list,空就调默认构造函数。

3.模板函数需要显示参数类型。

template<typename T>
void foo(T param) {}void test0()
{//foo({ 1, 2 });  // 错误:无法推导 T(必须显式指定为 std::initializer_list<int>)foo(initializer_list<int>{1, 2});
}

2.decltype自动推导类型

void test2()
{int a = 1;double b = 2.0;auto c = a + b;           //  auto不能作形参和返回值cout << typeid(c).name() << endl;    //  doublestring s;decltype(c) d;cout << typeid(d).name() << endl;     //  doubledecltype(s) e;cout << typeid(e).name() << endl;      //class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >
}

3.final 和override

 final 修饰类,类就变成了最终类,不能被继承,修饰虚函数,该虚函数不能被重写。            override 检查子类是否重写虚函数。

4. 显示调用默认构造函数

class A
{
public:A() = default;   //指定显示去生成默认构造函数,因为当自己写了构造函数,就不会默认生成,但如果传参不匹配,无法构造,又不能调用默认构造函数,会报错,所以显示调用。A(const int& a):_a(a){ }private:int _a = 20;
};void test3()
{A a;  //  当没有A() = default,会报错 
}

5.禁止拷贝

class B
{
private://  B(const B& b);  //  C++98 只声明,不实现,别人就无法拷贝对象,为了防止在类外定义,用private限定//  在C++11中定义了新的语法禁止拷贝B(const B& b)= delete;B& operator=(const B& b) = delete;
};

6.右值引用

void test5()
{// 左值通常都是变量// 右值通常都是常量(表达式或者函数返回的值)int a = 0;int& b = a;   // 左值引用 引用左值// 如果用 左值引用 引用右值要加constconst int& c = 0;// 右值引用 引用右值int&& d = 1;        // 节省空间int e = 1;    //  直接赋值和右值引用的区别,右值引用不需要开辟空间,拷贝对象// 右值引用 引用左值要加movecout << "e的类型:" << typeid(e).name() << endl;int&& f = move(e);     // f与e的地址一样。cout << "e的类型:" << typeid(e).name() << endl;auto f1 = move(e);e = 3;cout <<"e:"<< e << "  " <<"f:"<< f << endl;f = 2;cout <<"e:"<<e << "  " <<"f:"<< f << endl;//  右值引用的是常量,为什么f能改变呢?并且将e改变了int&& g = 1 + 2;int& h = g;  //  虽然不能对常量用& 但可以对g用&cout << "&h:" << &h << endl;cout << "&g:" << &g << endl;h = 5;cout << "g:" << g << "  " << "h:" << h << endl;//  可以通过h改变g}

move对对像本身没什么影响,将对象标记为可以移动的,可以调用vector或string的移动构造函数,但移动构造函数将原来对象对这片内存的权限取消了,给了新的对象,将原来的对象置空或0。
其实,右值引用的作用主要发挥在调用移动构造,只转移管理权,不开辟空间,减少了内存的开销。(前提是,如果要调用移动构造,move的对象你不再使用了),对于一般的,如上面的move的使用,与左值引用无异。

7.lambda表达式

格式: [捕捉列表](形参)->返回类型{函数体}

void test8()
{auto r3 = [](int x) {return x; };     // r3 is a name of lambdacout << typeid(r3).name() << endl;int a = 1;int b = 2;int y = 3;int x = 0;cout << "a:" << a << " " << "b:" << b << endl;auto r1=[&a, &b](int x, int y)->int{a++; b++; return x + y; };  //  [捕捉列表](形参)->返回类型{函数体}int ret=r1(x, y);cout << "a:" << a << " " << "b:" << b << "  " << "ret:" << ret << endl;// 不作列表只能捕捉同一作用域变量//传值捕捉的对象不能改变(值的大小)//auto rr = [a, b]() {//	int tmp = a;//	a = b;//	b = tmp;//	}     //  报错auto rr = [a, b]()mutable {int tmp = a; //  (改变了值的大小)a = b;b = tmp;     //  加mutable就可以了,但没意义,用引用捕获就行};// 用途vector<int> v{ 1,2,3,4,5,6,7,8,9,10 };int num = count_if(v.begin(), v.end(), [](int n) {return n % 3==0; }); //  num 大小为返回true的个数  //  count_if 返回满足条件的范围中的元素数cout <<"满足条件个数:"<< num << endl;//  for_each  将函数应用于范围for_each(v.begin(), v.end(), [](int& v) {cout << v << " "; });}结果:
class `void __cdecl test8(void)'::`2'::<lambda_1>
a:1 b:2
a:2 b:3  ret:3
满足条件个数:3
1 2 3 4 5 6 7 8 9 10

《C++ primer》解释

8.引用折叠与完美转发

核心规则: 只要有一个 &(左值引用),最终结果就是 T&(左值引用)。 只有全是 &&右值引用),最终结果才是 T&&(右值引用)。

template<class T>
void B1(T&& t) { cout << "void B(T&& t)" << endl; };
template<class T>
void B1(T& t) { cout << "void B(T& t)" << endl; };
template<class T>
void B1(const T&& t) { cout << "void B(const T&& t)" << endl; };
template<class T>
void B1(const T& t) { cout << "void B(const T& t)" << endl; };template<class T>
void A1(T&& t)     //第一次引用折叠
{//右值引用在第二次传参后,属性丢失//完美转发解决B1(t);//B1(std::forward<T>(t)); // 调用forward 发生第二次引用折叠
}void test9()
{int a = 1;const int b = 2;A1(a);           A1(b);       A1(move(a));   A1(move(b));  // 只有左值引用会引发引用折叠// int&& c = move(b);   //  不允许直接move有const修饰的对象const int&& c = move(b);// int&& c = move(const_cast<int>(b)); // 用const_cast,是const修饰的变量指向的数据是可以修改的,2是一个常量}结果:
void B(T& t)
void B(const T& t)
void B(T& t)
void B(const T& t)
可以看出在第二次传参时,值的属性消失
B1(std::forward<T>(t)); // 调用forward 发生引用折叠结果:
void B(T& t)
void B(const T& t)
void B(T&& t)
void B(const T&& t)属性没有丢失

根据折叠规则:

forward函数:

emplate<typename T>
T&& forward(std::remove_reference_t<T>& t) noexcept {return static_cast<T&&>(t);  // 引用折叠发生在这里
}

根据折叠规则:

如果 T是 int&: static_cast<int& &&>(t) → static_cast<int&>(t)(保持左值)。

如果 T是 int: static_cast<int&&>(t)(保持右值)。

forward很巧妙的使用了折叠的规则:

如果没有forward折叠,那么下面两种 int ,const int会被推导为int&,const int&

因:第一次折叠捣的鬼。

果:forward巧妙的借用了折叠鬼完成完美转发。

师夷长技以制夷。

在 A1(move(a)) 的场景中,虽然 A1()函数中的t 的类型已经是 int&&(右值引用),直接传递 t 似乎也能保留右值属性,但使用 std::forward 仍然必要

 直接传递 t 的问题 :右值引用变量 t是左值表达式,在 A1函数内部,t 是一个具名变量(即使它的类型是 int&&),而所有具名变量都是左值表达式。 

9.线程

int x = 0;
void Add2(int num)
{for (int i = 0; i < num; i++){++x;}
}void test10()
{thread t1(Add2, 1000000);thread t2(Add2, 1000000);t1.join();t2.join();     //  t1和t1 同时进行线程,对x加10000000次,会有冲突cout << "x:" << x << endl;   //  x<2000000}
不同的线程对同一个对象进行处理,会发生同时拿这个对象,同时加1,x只加一次结果(多次):
x:1044214
x:1052133
x:1187482

9.1锁的使用

mutex mtx;   // 不能将互斥锁放在Add3()里,不然每个线程创建自己的互斥锁
void Add3(int num)
{mtx.lock();for (int i = 0; i < num; i++){++m;}mtx.unlock();
}   // 串行void test10()
{// 互斥锁thread t3(Add3, 1000000);thread t4(Add3, 1000000);t3.join();t4.join();    cout << "m:" << m << endl;  }结果:
m:2000000

9.2原子

void test11()
{atomic<int> x2 = 0;auto Add5 = [&x2](int num) {for (int i = 0; i < num; i++){++x2;}};thread t1(Add5, 1000000);thread t2(Add5, 1000000);cout << t1.get_id() << endl;cout << t2.get_id() << endl;t1.join();t2.join();  cout << "x:" << x2 << endl;    // 原子不上锁,也准确。}

原子不会有冲突。

9.3条件变量

成员


双线程打印1~100,一个线程打印奇数,另一个线程打印偶数

void test13()
{int num = 100;condition_variable cv1;condition_variable cv2;mutex m1;mutex m2;thread t1([&]() {for (int i = 0; i < num; i += 2){if (i)    // 第一次不锁{unique_lock<mutex>lock1(m1);cv1.wait(lock1);}cout << this_thread::get_id() << ":" << i << endl;cv2.notify_one();}});thread t2([&]{for (int i = 1; i < num; i += 2){unique_lock<mutex>lock2(m2);cv2.wait(lock2);cout << this_thread::get_id() << ":" << i << endl;cv1.notify_one();}});t1.join();t2.join();}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/88867.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/88867.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI代码助手实践指南

概述与发展趋势 核心理念 发展方向&#xff1a;从代码补全 → 代码生成 → 整个工程服务价值转换&#xff1a;从单纯写代码 → 需求驱动的代码生成功能扩展&#xff1a;超越编写层面&#xff0c;涵盖测试环境搭建等 核心价值点 低价值动作识别&#xff1a;debug、代码评审、…

.net反编译工具

.NET 反编译工具大揭秘 在.NET 开发的世界里&#xff0c;有时候我们需要对已编译的.NET 程序集进行反编译&#xff0c;将 DLL 或 EXE 文件还原为可读的源代码形式&#xff0c;这在学习、调试、代码分析等方面都有着重要的作用。今天&#xff0c;就让我们一起深入了解一些流行的…

mac docker desktop 安装 oracle

1.登录 oracle 官网&#xff0c;选择镜像 https://container-registry.oracle.com/ords/f?p113:1:6104693702564::::FSP_LANGUAGE_PREFERENCE:&cs3CAuGEkeY6APmlAELFJ0uYU5M8_O8aTEufSKZHFf12lu1sUk5fsdbCzJAni9jVaCYXf-SNM_8e3VYr1V4QMBq1A 2.登录认证 oracle 账号 doc…

【redis使用场景——缓存——数据过期策略 】

redis使用场景——缓存——数据过期策略 定期删除&#xff08;Active Expiration&#xff09;1. 快速模式&#xff08;Fast Expiration Cycle&#xff09;工作流程&#xff1a;特点&#xff1a;优点&#xff1a; 2. 慢速模式&#xff08;Slow Expiration Cycle&#xff09;工作…

智能体Manus和实在Agent的区别

在当今数字化时代&#xff0c;AI 已经深度融入我们的生活和工作。曾经&#xff0c;像 ChatGPT 这样的传统 AI&#xff0c;虽然能在很多方面给我们提供帮助&#xff0c;比如写邮件时它妙笔生花&#xff0c;分析数据时头头是道&#xff0c;可却在最后一步掉了链子 —— 它不会点击…

Prism框架实战:WPF企业级开发全解

以下是一个完整的WPF项目示例&#xff0c;使用Prism框架实现依赖注入、导航、复合命令、模块化和聚合事件功能。项目结构清晰&#xff0c;包含核心功能实现&#xff1a; 项目结构 PrismDemoApp/ ├── PrismDemoApp (主项目) │ ├── Views/ │ │ ├── ShellView…

单片机学习笔记---AD/DA工作原理(含运算放大器的工作原理)

目录 AD/DA介绍 硬件电路模型 硬件电路 运算放大器 DA原理 T型电阻网络DA转换器 PWM型DA转换器 AD原理 逐次逼近型AD转换器 AD/DA性能指标 XPT2046 XPT2046时序 AD/DA介绍 AD&#xff08;Analog to Digital&#xff09;&#xff1a;模拟-数字转换&#xff0c;将模拟…

matlab实现相控超声波成像

相控超声波成像仿真检测探伤 数据接收 换能器开发 Phased Array Codes/Matlab Examples.pptx , 513230 Phased Array Codes/MATLAB M_files/delay_laws2D.m , 1027 Phased Array Codes/MATLAB M_files/delay_laws2D_int.m , 3290 Phased Array Codes/MATLAB M_files/delay_law…

Stable Diffusion入门-ControlNet 深入理解 第二课:ControlNet模型揭秘与使用技巧

大家好&#xff0c;欢迎回到Stable Diffusion入门-ControlNet 深入理解系列的第二课&#xff01; 如果你还记得第一篇文章的内容 - 我们已经了解了 ControlNet 的基础概念&#xff1a;它通过预处理器和模型两个强力模块&#xff0c;赋予了AI绘画前所未有的精准控制。 还没看过…

大数据时代UI前端的变革:从静态展示到动态交互

hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在大数据时代&#xff0c;信息以前所未有的速度和规模增长。这种数据环境的变化&#xff0c;深…

引脚个数、引脚宽度、引脚之间距离

原图&#xff1a; 最终效果图如下&#xff1a; 1.读取图片并设置参数 read_image (Image, ic_pin) dev_set_draw (margin) dev_set_line_width (2) dev_get_window (WindowHandle) get_image_size (Image, Width, Height) 2.绘制提取的ROI区域 r:58 // 旋转矩形的中心点坐标…

内网和外网有什么区别?如何将内网ip端口地址映射到外网用?

由于局域网的使用&#xff0c;区分出了内网和外网两种概念。以路由器为核心&#xff0c;可以将多台电脑组建成一个局域网&#xff0c;局域网之内的网络便是内网。内网是有距离限制的&#xff0c;只有在路由器信号范围内的电脑才能接入局域网&#xff0c;否则需要进行内网穿透技…

Git仓库的原理理解

国内外主流的 Git 代码托管平台 (持续更新) - JetsungChan - 博客园 .gitignore文件讲解( 忽略规则文件 )[重点] (主要目的是为了节省空间 , 不必要的文件不要管他 , 忽略掉) 重复文件的云储存(只会上传一份) (所以不要怕stm32每个工程文件 , 有几十M , 全部上传会太大 . 实际…

011 Linux进程

&#x1f984; 个人主页: 小米里的大麦-CSDN博客 &#x1f38f; 所属专栏: Linux_小米里的大麦的博客-CSDN博客 &#x1f381; GitHub主页: 小米里的大麦的 GitHub ⚙️ 操作环境: Visual Studio 2022 文章目录 深入理解 Linux 进程管理一、管理哲学/本质&#xff1a;先描述&am…

星型模型(Star Schema)

在数据仓库的体系概念中&#xff0c;星型模型&#xff08;Star Schema&#xff09;和雪花模型&#xff08;Snowflake Schema&#xff09;是两种常见的数据模型&#xff0c;用于组织和结构化数据&#xff0c;以支持高效的查询和分析。 今天我们先介绍星型模型&#xff08;Star …

【RAG面试题】如何获取准确的语义表示

目录 回答模板 语义表示是干什么的&#xff1f; 如何获取准确语义表示的关键步骤&#xff1f; 1. 选择合适的 Embedding 模型 2. 正确的文本预处理与切分 3. 文本清洗与标准化 4. 构建合理的向量库 5. 检索质量验证与优化 详细知识点覆盖 面试回答技巧 回答模板…

小程序 API 开发手册:从入门到高级应用一网打尽

在移动互联网浪潮中&#xff0c;小程序已经成为企业服务用户的“第二战场”。不论是微信小程序、支付宝小程序&#xff0c;还是抖音小程序&#xff0c;都在强调一个核心能力&#xff1a;快速响应用户需求。而支撑小程序灵活运行和丰富功能的关键技术之一&#xff0c;正是小程序…

iwebsec靶场sqli注入(2)

​​​​​​06-宽字节注入 1&#xff0c;该漏洞的根本原因是字符集处理不一致&#xff08;GBK双字节特性&#xff09;与不安全的转义方式&#xff08;addslashes&#xff09;共同导致。构造基础sql注入语句 1%df%27%20%23 漏洞原理 字符集设置&#xff1a;mysql_query("S…

小程序学习笔记:自定义组件创建、引用、应用场景及与页面的区别

在微信小程序开发中&#xff0c;自定义组件是一项极为实用的功能&#xff0c;它能有效提高代码的复用性&#xff0c;降低开发成本&#xff0c;提升开发效率。本文将深入剖析微信小程序自定义组件的各个关键方面&#xff0c;包括创建、引用、应用场景以及与页面的区别&#xff0…

开发数字化绿色低碳园区系统:分阶段实施指南

目录 摘要 背景 核心模块 阶段性开发 分阶段开发实施 第一阶段(3-6个月):搭建核心骨架 第二阶段(6-9个月):扩展功能 第三阶段(9-12个月):深度定制 技术选型 注意事项 实施计划表 小结 摘要 数字化绿色低碳园区系统通过物联网、能源管理和数据分析等技术,…