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

面试之快速学习C++14

文章参考:https://zhuanlan.zhihu.com/p/588826142?utm_id=0

最近学了一会感慨到找工作好难,上周面试了一家医疗公司,准备攒攒经验但是不去,结果三天了没消息,感觉一面都没过…

本来自傲看不上,结果人家也看不上你…没事攒攒经验,面试官问了是否会C++14我说我不会,问题不大,现在看看来得及~

1. 变量模版

/*1. 变量模版 ------------*/
//1.引入的意义,以前只有模版类和模版函数,比如我想定义一个各种类型的常量,那么不能用模版,C++14可以了
template <typename T>
constexpr T pi = T(3.1415926);//类内模版变量的定义
struct VariableTemplate1 {template<typename T>static T min;
};
//注意这里要加一个T ,min会使用默认值
template<typename T>
T VariableTemplate1::min = {};//但是你可以偏特化
template<>
const float VariableTemplate1::min<float> = 6.666;
template<>
const std::string VariableTemplate1::min<std::string> = "hhh";
//我可以理解为,变成了三个变量?
//变量模版和类型推导
template <typename T>
constexpr T pi1 = T{3.1415926};void testVariableTemplate() {//pi是一个doubledouble diameter = 2 * pi<double> * 3;std::cout << "diameter<double> = " << diameter <<std::endl;//pi是一个intdiameter = 2 * pi<int> * 3;std::cout << "diameter<int> = " << diameter <<std::endl;VariableTemplate1::min<int> = 3;std::cout << "VariableTemplate1::min = " << VariableTemplate1::min<int> <<std::endl;//    VariableTemplate1::min<std::string> = "hhh"; //会报错,因为int模版对应了默认的模版值,现在不知道对应哪个模版std::cout << "VariableTemplate1::min = " << VariableTemplate1::min<std::string> <<std::endl;std::cout << "VariableTemplate1::min = " << VariableTemplate1::min<double> <<std::endl;std::cout << "VariableTemplate1::min = " << VariableTemplate1::min<float> <<std::endl;//0  ???是不是因为第一次确定类型之后就不会改了auto pi3 = pi<int>;auto pi4 = pi<double>;auto pi5 = pi<char>;std::cout << "pi3 = " << pi3 <<std::endl;std::cout << "pi4 = " << pi4 <<std::endl;std::cout << "pi5 = " << pi5 <<std::endl;/*diameter<double> = 18.8496diameter<int> = 18VariableTemplate1::min = 3VariableTemplate1::min = hhhVariableTemplate1::min = 0VariableTemplate1::min = 6.666pi3 = 3pi4 = 3.14159pi5 = */}

问题

  1. 为什么一个min可以对应这么多值?所以实际上它是会根据实例化的值生成一个单独的值?

感受
1 . 它可以与auto配合使用去做类型转换,生成不同的常量。
2 . 可以用于在一个类里面定义很多不同类型的静态常量

2.lambda

/*2. lambda表达式的改动 ------------*/
//1. 支持lamda泛型参数
//2. 支持初始化捕获void testLambda() {int x = 7;//捕获x并给它初始值,意义在哪里?auto func = [x = 3](auto y) {return x+y;};//泛型参数这个比较好理解,初始化捕获有什么好处呢。在c++11中,lambda表示捕获变量只能通过值捕获或者引用捕获,支持了初始化表达式之后,我们就可以更灵活的捕获了,比如移动捕获std::string str = "xixixixi";std::string str1;auto func1 = [str1 = std::move(str)]{return str1 + ", hhhhhh";};std::cout << "func(3)" << func(3) << std::endl;std::cout << "func(4.5)" << func(4.5) << std::endl;std::cout << "func1()" << func1() << std::endl;/*func(3)6func(4.5)7.5func1()xixixixi, hhhhhh*/
}
//如果有学习c++11的function、bind以及lambda表达式,你应该会知道bind相对于lambda表达式的两个最重要的优势就是泛型参数和移动捕获,从c++14之后,bind的这个两个优势就完全不复存在了,并且lambda表达式对象会比bind生成的对象更小,所以基本上可以让bind光荣的下岗了(但是实际bind到了c++20以后也依旧存在,哪可能有它存在的意义把)。

3. constexpr限制放宽

/*
3. constexpr限制放宽------c++11中constexpr修饰变量,要求变量必须是可以在编译器推导出来;
constexpr修饰函数(其实就是修饰函数返回值),除了可以包含 using 指令、typedef 语句以及 static_assert 断言外,只能包含一条 return 返回语句;
constexpr同时可以修饰构造函数,但是也会要求使用这个构造函数时,可以在编译器就把相关的内容全部推导出来
c++14中,对constexpr的限制放宽了,允许使用循环、if、switch等等语句,但是主旨还是一样的,需要在编译期间就可以计算出全部内容,限制放宽之后,这个关键字便可以更灵活的使用了。*/
//比如在c++11中如果想用constexpr计算前n项和,那么需要像下面这样写constexpr int testConexpresFunc1(int n) {return n > 0 ? testConexpresFunc1(n - 1) +  n : 0;
}//在c++14中就可以使用if、局部变量和循环了(c++14可以,c++11报错)
constexpr int testConexpresFunc2(int n) {if (n <= 0){return 0;}int sum = 0;for (int i = 1; i <= n; ++i) {sum += i;}return sum;/*testConexpresFunc1(5) = 15testConexpresFunc2(5) = 15*/
}

4. 数字分隔符

    // 三个数字的结果完全一样int val1 = 100000000;int val2 = 100'000'000;int val2 = 100'00'0'0'0'0;

5. 函数返回值推导


/*5. 函数返回值推导 ------------*///回顾c++11返回值类型后置,一定要auto + decltype
template<typename T, typename U>
auto add1(T a, U b)->decltype(a+b) {return a+b;
}//c++14之后相当于不需要decltype了
template<typename T, typename U>
auto add2(T a, U b) {return a+b;
}//限制条件如下:
//1. 如果有多个推导语句,那么推导的结果必须保持一致,实际上编译器就是根据函数里面的return推导的吧!
// 编译报错,第一个return推导为int,第二个return推导为double,两次推导结果不一致
//报错: 'auto' in return type deduced as 'double' here but deduced as 'int' in earlier return statement
//auto add3 (int flag)
//{
//    if (flag < 0)
//    {
//        return 1 ;
//    }
//    else
//    {
//        return 3.14;
//    }
//}//2.如果没有return或者return为void类型,那么auto会被推导为void。
//3. 一旦在函数中看到return语句,从该语句推导出的返回类型就可以在函数的其余部分中使用,包括在其他return语句中,即,优先推导论,优先推导是什么类型就是类型。
auto add4(int i)
{if (i <= 1){return i; // 返回值被推导为int}else{return add4(i - 1) + i; // sum的返回值已经被推导出来了,所以这里是没有问题的}
}
//报错:Function 'add5' with deduced return type cannot be used before it is defined
//auto add5(int i)
//{
//    if (i > 1)
//    {
//        return add5(i - 1) + i;
//    }
//    else
//    {
//        return i;
//    }
//}
//4. 不能推导初始化列表。
//报错:Cannot deduce return type from initializer list
//auto add6(int i)
//{
//    return {1,2,3,4};
//}
//5. 虚函数不能使用返回值推导void testTrailingReturnType() {std::cout << "add1(5,2) = " << add1(5,2) << std::endl;std::cout << "add2(5,2) = " << add2(5,2) << std::endl;std::cout << "add4(5,2) = " << add4(5) << std::endl;/*add1(5,2) = 7add2(5,2) = 7add4(5,2) = 15*/
}

6. [[deprecated]]标记

美 [ˈdeprəkeɪtɪd]
vt. 强烈反对,抨击;对……表示不赞成;


/*6. [[deprecated]]标记 ------------*/
//在打算废弃一些接口的时候,可以直接打个标记过渡,然后在后续的版本就可以完全清理掉。
[[deprecated]]
void deprecatedFunc() {//do nothing
}void testDeprecatedFunc() {//warning'deprecatedFunc' is deprecateddeprecatedFunc();
}

7. 库的新特性

/*库的新特性*/
/*7. 新增std::make_unique*/
class A {
public:A(const int a):a_(a){}int getA(){return a_;}
private:int a_;
};
void testMakeUnique() {//新增std::make_uniquestd::unique_ptr<A> pt = std::make_unique<A>(1);std::cout << "pt = " << pt->getA() << std::endl;
}/*2.新增读写锁std::shared_timed_mutex与std::shared_lock*/
//c++11引入了多线程线程的一些库,但是是没有读写锁的,因此在c++14引入了读写锁的相关实现(头文件shared_mutex),其实c++14读写锁也还不够完善,知道c++17读写锁这块才算是完备起来,后面写c++17的时候计划把这块再完整的梳理一下。
/* 当Mutex是shared_mutex 的时候1.当有函数使用共享锁时,能够与其他享有共享锁的函数也能并发同步执行。而和所有独占锁的函数是互斥的。2.当有一个函数使用独占锁时,其他所有的用同一个Mutex带锁的函数都是与其互斥的。
*/
//我理解是这个std::shared_mutex实际上是互斥量,是否是共享锁取决于用std::shared_lock<std::shared_mutex> ,还是std::unique_lock<std::shared_mutex> 还是std::lock_guard<std::shared_mutex>std::shared_mutex g_sMutex;
std::shared_timed_mutex g_shared_m;
void writeTime(const std::string funName ,int time) {for (size_t i = 1; i < time; i++) {std::string outPut = funName + ":" + std::to_string(time);std::cout << outPut << std::endl;sleep(1);}}void shared_1(int seconds) {std::shared_lock<std::shared_timed_mutex> sl(g_shared_m);std::cout << "shared_1" << std::endl;writeTime("shared_1" , seconds);
}void shared_2(int seconds) {std::shared_lock<std::shared_timed_mutex> theLock(g_shared_m);std::cout << "shared_2" << std::endl;writeTime("shared_2", seconds);
}void testSharedMutext() {std::vector<std::thread> vecThrea;vecThrea.push_back(std::thread(shared_1,10));vecThrea.push_back(std::thread(shared_2,10));for (auto & oneThread : vecThrea){oneThread.join();}/*shared_1shared_2shared_2:10shared_1:10shared_2:10shared_1:10shared_2:10shared_1:10shared_1:10shared_2:10shared_1:10shared_2:10shared_1:10shared_2:10shared_1:10shared_2:10shared_2:10shared_1:10shared_2:10shared_1:10*/
}
/*3. 新增std::exchange*/
//c++14新增了一个接口std::exchange(头文件utility),其实这个也并不算是新增的,因为这个接口其实在c++11的时候就有了,只不过在c++11中作为一个内部函数,不暴露给用户使用,在c++14中才把它暴露出来给用户使用。使用方法也很简单。
//exchange会把第二个值赋值给第一个值,但是不会改变第二个值。我们来看下它的实现吧。//自己仿写一个, 除此之外,我们这里说明一个关键的点。exchange的第二个值是万能引用,所以说他是既可以接收左值,也可以接收右值的,所以我们可以这样来使用。
template <typename T, typename U>
T myExchange(T &a, U &&b) {T old_value = std::move(a);a = std::forward<U>(b);return old_value;
}void testExchange() {std::string s1 = "hello";std::string s2 = "world";std::cout << s1 << " " << s2 << std::endl;std::exchange(s1, s2);std::cout << s1 << " " << s2 << std::endl;/*hello  worldworld world*/myExchange(s1, s2);std::cout << s1 << " " << s2 << std::endl;myExchange(s1, std::move(s2));std::cout << s1 << "|  " << s2 << std::endl;/*hello worldworld worldworld worldworld|*/}/*4. 新增std::quoted英  [kwəʊtid]   美  [ˈkwoʊtɪd]
v. 引证(quote 的过去式)*/
//C++14引入std::quoted用于给字符串添加双引号void testQuoted() {std::string str = "Hello world!";std::cout << str << std::endl;std::cout << std::quoted(str) << std::endl;/*Hello world!"Hello world!"*/
}

相关文章:

面试之快速学习C++14

文章参考&#xff1a;https://zhuanlan.zhihu.com/p/588826142?utm_id0 最近学了一会感慨到找工作好难&#xff0c;上周面试了一家医疗公司&#xff0c;准备攒攒经验但是不去&#xff0c;结果三天了没消息&#xff0c;感觉一面都没过… 本来自傲看不上&#xff0c;结果人家也…...

【算法专题突破】双指针 - 快乐数(3)

目录 1. 题目解析 2. 算法原理 3. 代码编写 写在最后&#xff1a; 1. 题目解析 题目链接&#xff1a;202. 快乐数 - 力扣&#xff08;Leetcode&#xff09; 这道题的题目也很容易理解&#xff0c; 看一下题目给的示例就能很容易明白&#xff0c; 但是要注意一个点&#…...

【javaweb】学习日记Day4 - Maven 依赖管理 Web入门

目录 一、Maven入门 - 管理和构建java项目的工具 1、IDEA如何构建Maven项目 2、Maven 坐标 &#xff08;1&#xff09;定义 &#xff08;2&#xff09;主要组成 3、IDEA如何导入和删除项目 二、Maven - 依赖管理 1、依赖配置 2、依赖传递 &#xff08;1&#xff09;查…...

C++信息学奥赛1144:单词翻转

#include <iostream> #include <string> using namespace std; int main() {string str;// 输入一行字符串getline(cin, str);string arr;for (int i 0; i < str.length(); i){if (str[i] ! ){arr str[i]; // 将非空格字符添加到临时存储的字符串中}else{for…...

qt检查文件夹是否有写权限

Qt 使用如下函数能够判断路径或者文件是否可写&#xff1a; bool QFileInfo::isWritable() const 对于win10系统实测&#xff0c;结果不准确。继续排查&#xff0c;官方文档描述&#xff1a;a&#xff09;如果未启用 NTFS 权限检查&#xff0c;Windows 上的结果将仅反映文件是…...

LSF 安装目录,快速参考 LSF 命令、守护程序、配置文件、日志文件和重要集群配置参数

样本 UNIX 和 Linux 安装目录 守护程序错误日志文件 守护程序错误日志文件存储在 LSF_LOGDIR 在 lsf.conf 文件中定义的目录中。 LSF 基本系统守护程序日志文件LSF 批处理系统守护程序日志文件pim.log.host_namembatchd.log.host_namembatchd.log.host_namesbatchd.log.host_…...

在Mybatis中写动态sql这些标签:if、where、set、trim、foreach、choose的作用是什么,怎么用?

在 MyBatis 中&#xff0c;您可以使用动态 SQL 标签来构建灵活的 SQL 查询&#xff0c;以根据不同的条件生成不同的查询语句。以下是这些标签的作用和用法&#xff1a; 1. **<if> 标签&#xff1a;** 用于根据某个条件动态地包含或排除 SQL 片段&#xff0c;test:可以写…...

7 Python的模块和包

概述 在上一节&#xff0c;我们介绍了Python的异常处理&#xff0c;包括&#xff1a;异常、异常处理、抛出异常、用户自定义异常等内容。在这一节中&#xff0c;我们将介绍Python的模块和包。Python的模块&#xff08;Module&#xff09;和包&#xff08;Package&#xff09;是…...

【JavaWeb 篇】使用Servlet、JdbcTemplate和Durid连接池实现用户登录功能与测试

在现代Web应用程序开发中&#xff0c;用户登录功能是基础中的基础。它为用户提供了安全访问系统的途径。本篇博客将引导您通过使用Servlet、Spring框架的JdbcTemplate以及Durid连接池&#xff0c;来构建一个完整的用户登录功能。我们将详细展示每个部分的代码&#xff0c;并解释…...

【Unity3D赛车游戏】【六】如何在Unity中为汽车添加发动机和手动挡变速?

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…...

【Go 基础篇】切片:Go语言中的灵活数据结构

在Go语言中&#xff0c;切片&#xff08;Slice&#xff09;是一种强大且灵活的数据结构&#xff0c;用于管理和操作一系列元素。与数组相比&#xff0c;切片的大小可以动态调整&#xff0c;这使得它成为处理动态数据集合的理想选择。本文将围绕Go语言中切片的引入&#xff0c;介…...

龙芯2K1000LA移植交叉编译环境以及QT

嵌入式大赛结束了&#xff0c;根据这次比赛中记的凌乱的笔记&#xff0c;整理了一份龙芯2K1000LA的环境搭建过程&#xff0c;可能笔记缺少了一部分步骤或者错误&#xff0c;但是大致步骤可以当作参考。 一、交叉编译工具链 下载连接&#xff1a;龙芯 GNU 编译工具链 | 龙芯开…...

javaee spring依赖注入之spel方式

spring依赖注入之spel方式 <dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>4.3.18.RELEASE</version></dependency>package com.test.pojo;import java.util.List; …...

【Java集合学习1】ArrayList集合学习及集合概述分析

JavaArrayList集合学习及集合学习概述 一、Java集合概述 Java 集合&#xff0c; 也叫作容器&#xff0c;主要是由两大接口派生而来&#xff1a;一个是 Collection接口&#xff0c;主要用于存放单一元素&#xff1b;另一个是 Map 接口&#xff0c;主要用于存放键值对。对于Col…...

TouchGFX之调试

DebugPrinter类是一种在显示屏上打印调试消息的简单方法&#xff0c;无需向屏幕添加控件。 在使用DebugPrinter之前&#xff0c;需要分配一个实例并将其传递给Application类&#xff0c;且DebugPrinter实例必须兼容所使用的LCD类。 该表列出了DebugPrinter类名称&#xff1a; …...

C# winform加载yolov8模型测试(附例程)

第一步&#xff1a;在NuGet中下载Yolov8.Net 第二步&#xff1a;引用 using Yolov8Net; 第三步&#xff1a;加载模型 private IPredictor yolov8 YoloV8Predictor.Create("D:\\0MyWork\\Learn\\vs2022\\yolov_onnx\\best.onnx", mylabel); 第四步&#xff1a;图…...

浙大陈越何钦铭数据结构07-图6 旅游规划

题目: 有了一张自驾旅游路线图&#xff0c;你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序&#xff0c;帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的&#xff0c;那么需要输出最便宜的一条路径。 输入…...

VUE笔记(七)项目登录

1、安装elementui 在终端执行 vue add element 注册组件 如果要使用哪个组件&#xff0c;大家需要在plugins/element.js中注册该组件 import Vue from vue import { Button } from element-ui Vue.use(Button) 在页面组件中使用 <el-button type"primary"&…...

大语言模型之六- LLM之企业私有化部署

数据安全是每个公司不得不慎重对待的&#xff0c;为了提高生产力&#xff0c;降本增效又不得不接受新技术带来的工具&#xff0c;私有化部署对于公司还是非常有吸引力的。大语言模型这一工具结合公司的数据可以大大提高公司生产率。 私有化LLM需要处理的问题 企业内私有化LLM…...

Python3 列表

Python3 列表 序列是 Python 中最基本的数据结构。 序列中的每个值都有对应的位置值&#xff0c;称之为索引&#xff0c;第一个索引是 0&#xff0c;第二个索引是 1&#xff0c;依此类推。 Python 有 6 个序列的内置类型&#xff0c;但最常见的是列表和元组。 列表都可以进…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...