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

【标准库的典型内容】std::declval

一、 d e c l v a l declval declval的基本概念和常规范例

s t d : : d e c l v a l std::declval std::declval C + + 11 C++11 C++11标准中出现的一个函数模板。这个函数模板设计的比较奇怪(没有实现,只有声明),因此无法被调用,通常是和 d e c l t y e decltye decltye s i z e o f sizeof sizeof等关键字一起使用,来进行类型推导等等。


下面是 d e c l v a l declval declval的一般源码实现:

//declval的源码形式,只有声明没有实现,一般是配合decltype使用的
template<typename T>
std::add_rvalue_reference_t<T>declval() noexcept;

这里的 s t d : : a d d _ r v a l u e _ r e f e r e n c e _ t std::add\_rvalue\_reference\_t std::add_rvalue_reference_t s t d : : a d d _ r v a l u e _ r e f e r e n c e std::add\_rvalue\_reference std::add_rvalue_reference的别名模板,用于将传入的类型加入 & & \&\& &&,下面是它的使用:


//将传入的类型加上两个&&
void Test1() {using Type1 = std::add_rvalue_reference<int>::type;std::cout << "Type1 = " << type_id_with_cvr<Type1>().name() << "\n";using Type2 = std::add_rvalue_reference<int&>::type;std::cout << "Type2 = " << type_id_with_cvr<Type2>().name() << "\n"; //折叠后还是&using Type3 = std::add_rvalue_reference<int&&>::type;std::cout << "Type3 = " << type_id_with_cvr<Type3>().name() << "\n"; //折叠后还是&&//也可以是用别名模板using Type4 = std::add_rvalue_reference_t<const int>;std::cout << "Type4 = " << type_id_with_cvr<Type4>().name() << "\n";}

一般在传入参数的时候,会发生折叠引用,如 & + & & = & \&+\&\& = \& &+&&=&,这里不多讨论。

下面是运行结果:

在这里插入图片描述

至于为什么返回右值引用,而不返回左值引用,下面将会介绍。


二、 s t d : : d e c l v a l std::declval std::declval的使用

2.1 类 A A A的实现

首先,我们存在这么一个类 A A A,用于测试:

//std::declval的简单使用
class A {
public:A(int i) {std::cout << "A::A()函数执行了,this = " << this << "\n";}double myfunc(double x = 12.1) {std::cout << "A::myfunc()函数执行了,this = " << this << "\n";return x;}
};

2.2 推导 d e c l v a l declval declval返回的类名

然后,我们可以利用 d e c l t y p e + d e c l v a l decltype+declval decltype+declval来推导 A A A的类型名,如下,注意 d e c l v a l declval declval后面需要跟着一个 ( ) () ()表示函数调用:

using YT = decltype(std::declval<A>()); //将A转为右值引用std::cout << "YT = " << type_id_with_cvr<YT>().pretty_name() << "\n";

返回的类型是 A A A & & \&\& &&进行折叠后的结果,是一个右值引用类型。

在这里插入图片描述


2.3 推导 d e c l v a l declval declval返回的函数返回值类型

在类 A A A存在成员函数,如果我们想要推导这个成员函数的返回值类型,我们需要怎么做呢?

通常情况下,我们可能这样写代码:

A tmp(1);
std::cout << "mydouble() 返回类型 = " <<type_id_with_cvr<decltype((tmp.myfunc()))>().pretty_name() << "\n";

然而,这样推导会调用这个函数,如下:

在这里插入图片描述


但是,如果我们通过 d e c l v a l declval declval来推导返回值,就不会调用这个函数,这也是 d e c l v a l declval declval的使用场景之一,并且,由于没有实例化出这个类,我们无需提供它的构造函数参数(如果存在),如下:

//如果不想调用函数而推导处函数返回值,因为decltype不会调用函数
std::cout << "mydouble() 返回类型 = " <<type_id_with_cvr<decltype(std::declval<A>().myfunc())>().pretty_name() << "\n";

可以发现,没有调用函数就推导出了其返回值类型:

在这里插入图片描述


这样的写法可以看做 d e c l v a l < A > ( ) declval<A>() declval<A>()返回一个 A & & A\&\& A&&的临时变量,然后这个临时变量调用了 m y f u n c ( ) myfunc() myfunc()函数。

可以参考下面的写法:
在这里插入图片描述
如果直接调用 a y i n o b j k ( ) ayinobjk() ayinobjk(),将会链接错误,因为这个函数没有实现。
而如果通过 d e c l t y p e decltype decltype,那么将不会编译失败,也不会链接失败:

下图的写法实际上是推导出了 d o u b l e double double类型,然后定义了 d o u b l e double double类型的变量 m y d b l v a l mydblval mydblval
在这里插入图片描述
通过这个例子,也就可以理解了 d e c l v a l < A > ( ) . m y f u n c ( ) declval<A>().myfunc() declval<A>().myfunc()的写法了。


三、 d e c l v a l declval declval返回右值的原因

3.1 返回值自身的问题

首先我们实现三种返回值的 d e c l v a l declval declval

//返回值
template<typename T>
T mydeclval() noexcept; //只声明,无法被调用//返回右值引用
template<typename T>
T&& mydeclval2() noexcept; //只声明,无法被调用//返回左值引用也行
template<typename T>
T& mydeclval3() noexcept; //只声明,无法被调用

我们类 A A A中加入一个 p r i v a t e private private的析构函数:

//std::declval的简单使用
class A {
public:A(int i) {std::cout << "A::A()函数执行了,this = " << this << "\n";}double myfunc(double x = 12.1) {std::cout << "A::myfunc()函数执行了,this = " << this << "\n";return x;}private:~A() {std::cout << "A::~A()函数执行了\n";}
};

此时,如果我们使用返回值类型的 d e c l t y p e decltype decltype语义上将会编译错误:

std::cout << "mydeclval<A>的返回类型 = " << type_id_with_cvr<decltype(mydeclval<A>())>().pretty_name() << "\n";
//无法被析构,从语义上要实例化一个临时对象A(尽管实际上并不会)
std::cout << "mydeclval<A>的返回类型 = " << type_id_with_cvr<decltype(mydeclval<A>().myfunc())>().pretty_name() << "\n";//同样的还有sizeof,也会编译失败
std::cout << "mydeclval<A>的大小 = " << sizeof(mydeclval<A>()) << "\n";

因为是返回值类型,所以会生成一个临时变量,但是这个临时变量的析构函数在 p r i v a t e private private内,无法被析构,因此编译器会报错(编译器无法生成一个不能析构的变量),即使使用 d e c l t y p e decltype decltype不会实例化出任何类型。


如果这里使用左值引用或右值引用的返回类型,就可以顺利通过编译了,因为是返回引用,所以无需考虑创建副本、析构的问题,因此在语义上是能通过编译的:


std::cout << "mydeclval<A>的返回类型 = " << type_id_with_cvr<decltype(mydeclval<A>())>().pretty_name() << "\n";
//无法被析构,从语义上要实例化一个临时对象A(尽管实际上并不会)
std::cout << "mydeclval<A>的返回类型 = " << type_id_with_cvr<decltype(mydeclval<A>().myfunc())>().pretty_name() << "\n";//同样的还有sizeof,也会编译失败
std::cout << "mydeclval<A>的大小 = " << sizeof(mydeclval<A>()) << "\n";

3.2 返回左值引用还是右值引用

我们知道,如果形参是 & \& &,那么通过折叠引用返回的类型永远都将是 & \& &,左值引用,无法得到右值引用。

运行下面的代码:

//返回左值引用还是右值引用
void Test4() {//如果是右值引用std::cout << "返回值为A&&的折叠引用情况:\n";std::cout << "decltype<mydecltype2<A>()>返回类型为:" <<type_id_with_cvr<decltype(mydeclval2<A>())>().pretty_name() << "\n";std::cout << "decltype<mydecltype2<A&>()>返回类型为:" <<type_id_with_cvr<decltype(mydeclval2<A&>())>().pretty_name() << "\n";std::cout << "decltype<mydecltype2<A&&>()>返回类型为:" <<type_id_with_cvr<decltype(mydeclval2<A&&>())>().pretty_name() << "\n";std::cout << "\n";//如果是左值引用std::cout << "返回值为A&的折叠引用情况:\n";std::cout << "decltype<mydecltype3<A>()>返回类型为:" <<type_id_with_cvr<decltype(mydeclval3<A>())>().pretty_name() << "\n";std::cout << "decltype<mydecltype3<A&>()>返回类型为:" <<type_id_with_cvr<decltype(mydeclval3<A&>())>().pretty_name() << "\n";std::cout << "decltype<mydecltype3<A&&>()>返回类型为:" <<type_id_with_cvr<decltype(mydeclval3<A&&>())>().pretty_name() << "\n";}

可见,使用右值引用可以得到两种引用情况,而使用左值引用只能得到左值引用类型:

在这里插入图片描述

3.2 调用引用限定符修饰的成员函数

通常,成员函数可以用一些限定,写在函数的 ( ) () ()之后,如 c o n s t / & / & & const/\&/\&\& const/&/&&等等,而调用它的类型也必须满足这样的限定。
我们这里具体讨论一下,参考下方代码:

//调用引用限定符修饰的成员函数
class ALR {
public:void onAnyValue() {std::cout << "ALR::onAnyValue()函数执行了\n";}void onLvalue()& { //只能被ALR的左值对象调用std::cout << "ALR::onLvalue()函数执行了\n";}void onRvalue()&& { //只能被ALR的右值对象调用std::cout << "ALR::onRvalue()函数执行了\n";}
};void Test5() {//返回右值引用decltype(mydeclval2<ALR>().onAnyValue()); //成功,没有限制//decltype(mydeclval2<ALR>().onLvalue()); //失败,&& 不能调用 &decltype(mydeclval2<ALR>().onRvalue()); //成功,&& 调用&&decltype(mydeclval2<ALR&>().onAnyValue()); //成功,没有限制decltype(mydeclval2<ALR&>().onLvalue()); //成功,&+ && = &//decltype(mydeclval2<ALR&>().onRvalue()); //失败,&+&& = &,不能调用&&decltype(mydeclval2<ALR&&>().onAnyValue()); //成功,没有限制//decltype(mydeclval2<ALR&&>().onLvalue()); //失败,&&+ && = &&,不能调用&decltype(mydeclval2<ALR&&>().onRvalue()); //成功,&&+&& = &&//返回左值引用decltype(mydeclval3<ALR>().onAnyValue()); //成功,没有限制decltype(mydeclval3<ALR>().onLvalue()); //成功,&调用&//decltype(mydeclval3<ALR>().onRvalue()); //失败,& 调用&&decltype(mydeclval3<ALR&>().onAnyValue()); //成功,没有限制decltype(mydeclval3<ALR&>().onLvalue()); //成功,&+ & = &//decltype(mydeclval3<ALR&>().onRvalue()); //失败,&+& = &,不能调用&&decltype(mydeclval3<ALR&&>().onAnyValue()); //成功,没有限制decltype(mydeclval3<ALR&&>().onLvalue()); //成功,&&+ & = &,调用&//decltype(mydeclval3<ALR&&>().onRvalue()); //失败,&+&& = &,不能调用&&}

通过折叠引用,以上注释起来的部分将会编译失败,因为限定符不符。


通过观察,我们发现如果返回左值引用,那么将无法调用右值引用限定符的成员函数,而如果返回右值引用,则没有这种情况发生。 因此, d e c l v a l declval declval返回右值引用比较合适。

四、推导函数返回值

4.1 全局函数

使用 d e c l v a l declval declval可以用于推导函数返回值,参考下方模板:

//declval推导函数返回值
int myfunc(int a, int b) {std::cout << "调用了myfunc函数\n";return a + b;
}//函数模板用于推导函数返回值
template<typename T_F, typename... U_Args>
decltype(std::declval<T_F>()(std::declval<U_Args>()...)) TestFnRtnImpl(T_F func, U_Args... args) {std::cout << "---------------begin---------------\n";std::cout << "T_F:" << type_id_with_cvr<T_F>().pretty_name() << "\n";std::cout << "---------------end---------------\n";auto rtnvalue = func(args...);return rtnvalue;
}

如果调用以下函数:

//declval推导函数返回值
int myfunc(int a, int b) {std::cout << "调用了myfunc函数\n";return a + b;
}
auto res = TestFnRtnImpl(myfunc, 1, 2);

其中,上面的 d e c l t y p e ( s t d : : d e c l v a l < T _ F > ( ) ( s t d : : d e c l v a l < U _ A r g s > ( ) . . . ) ) decltype(std::declval<T\_F>()(std::declval<U\_Args>()...)) decltype(std::declval<T_F>()(std::declval<U_Args>()...))可以看做: i n t ( ∗ & & ) ( i n t , i n t ) ( i n t & & , i n t & & ) int(*\&\&)(int,int)(int\&\&,int\&\&) int(&&)(int,int)int&&,int&&类型。

即传入的函数名是一个函数指针,返回函数指针的右值引用。然后后面的一个 d e c l v a l declval declval用于展开参数包,注意 . . . ... ...的写法。


当然,我们也能使用 a u t o + d e c l t y p e auto+decltype auto+decltype的方式推导返回类型,也是一样的:

// 使用 decltype 和 auto 推导函数的返回类型
template<typename T_F, typename... U_Args>
auto TestFnRtnImpl2(T_F func, U_Args... args) -> decltype(func(args...)) {std::cout << "---------------begin---------------\n";std::cout << "T_F:" << type_id_with_cvr<T_F>().pretty_name() << "\n";std::cout << "---------------end---------------\n";return func(args...);
}

如下所示:

在这里插入图片描述

4.2 成员函数

同样的,也可以使用 d e c l v a l declval declval来推导成员函数返回值,只不过需要实例化出一个成员(不是静态成员函数),利用到的是成员函数指针和这个对象的地址。

参考下方代码:

//函数模板用于推导成员函数返回值
template<typename T_F, typename T_Obj, typename... U_Args>
decltype((std::declval<T_Obj*>()->*std::declval<T_F>())(std::declval<U_Args>()...))
TestFnRtnImp3(T_Obj* obj, T_F func, U_Args... args) {//绑定发生了偏移std::cout << "---------------begin---------------\n";std::cout << "T_F:" << type_id_with_cvr<T_F>().pretty_name() << "\n";std::cout << "T_Obj:" << type_id_with_cvr<T_Obj>().pretty_name() << "\n";std::cout << "---------------end---------------\n";return (obj->*func)(args...);
}//使用auto+decltype推导成员函数返回值
template<typename T_F, typename T_Obj, typename... U_Args>
auto TestFnRtnImp4(T_Obj* obj, T_F func, U_Args... args) -> decltype((obj->*func)(args...)) {//绑定发生了偏移std::cout << "---------------begin---------------\n";std::cout << "T_F:" << type_id_with_cvr<T_F>().pretty_name() << "\n";std::cout << "T_Obj:" << type_id_with_cvr<T_Obj>().pretty_name() << "\n";std::cout << "---------------end---------------\n";return (obj->*func)(args...);
}

只是,有个细节需要注意的,这里发生了绑定的偏移,原本绑定成员函数指针的变量绑定上了对象地址:
在这里插入图片描述同样的, ( s t d : : d e c l v a l < T _ O b j ∗ > ( ) − > ∗ s t d : : d e c l v a l < T _ F > ( ) ) ( s t d : : d e c l v a l < U _ A r g s > ( ) . . . ) (std::declval<T\_Obj*>()->*std::declval<T\_F>())(std::declval<U\_Args>()...) (std::declval<T_Obj>()>std::declval<T_F>())(std::declval<U_Args>()...),这里可以看做是: d o u b l e ( A ∗ ) : : ( d o u b l e ) ( d o u b l e & ) double (A*)::(double)(double\&) double(A)::(double)(double&),和之前的全局函数类似。

相关文章:

【标准库的典型内容】std::declval

一、 d e c l v a l declval declval的基本概念和常规范例 s t d : : d e c l v a l std::declval std::declval 是 C 11 C11 C11标准中出现的一个函数模板。这个函数模板设计的比较奇怪&#xff08;没有实现&#xff0c;只有声明&#xff09;&#xff0c;因此无法被调用&…...

深入了解package.json文件

在前端项目开发中&#xff0c;我们经常会遇到package.json文件。这个文件不仅是一个简单的配置文件&#xff0c;它还承担了项目管理的重任。下面&#xff0c;我们将深入探讨package.json文件的各个字段和作用&#xff0c;并通过实例来帮助你更好地理解和使用它。 package.json…...

【基础知识】网络套接字编程

套接字 IP地址 port&#xff08;端口号&#xff09; socket&#xff08;套接字&#xff09; socket常见API //创建套接字 int socket(int domain, int type, int protocol); //绑定端口 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); //监听套接字…...

小程序地图展示poi帖子点击可跳转

小程序地图展示poi帖子点击可跳转 是类似于小红书地图功能的需求 缺点 一个帖子只能有一个点击事件&#xff0c;不适合太复杂的功能&#xff0c;因为一个markers只有一个回调回调中只有markerId可以使用。 需求介绍 页面有地图入口&#xff0c;点开可打开地图界面地图上展…...

传统到AI 大数据分析的演变,颠覆智慧水电的未来?

传统到AI 大数据分析的演变&#xff0c;颠覆智慧水电的未来&#xff1f; 前言传统到AI 大数据分析的演变 前言 水电作为一种重要的能源形式&#xff0c;一直在我们的生活中扮演着至关重要的角色。而如今&#xff0c;随着科技的飞速发展&#xff0c;智慧水电和 AI 大数据应用的…...

while语句

1.while使用 打印1-10 #include<stdio.h> int main() {int a 1;while (10 > a){printf("%d\n", a);a 1;}return 0; } 2.while语句中的break&#xff0c;continue break&#xff1a; 跳出while语句 #include<stdio.h> int main() {int a 0;wh…...

机器学习(西瓜书)第 10 章 降维与度量学习

10.1 k近邻学习kNN k 近邻(k-Nearest Neighbor,简称kNN)学习是一种常用的监督学习方法,其工作机制非常简单&#xff1a;给定测试样本&#xff0c;基于某种距离度量找出训练集中与其最靠近的k个训练样本&#xff0c;然后基于这k个 “邻居”的信息来进行预测.通常&#xff0c;在…...

828华为云征文 | 云服务器Flexus X实例,Docker集成搭建Halo博客平台

828华为云征文 | 云服务器Flexus X实例&#xff0c;Docker集成搭建Halo博客平台 Halo博客平台是一款基于Java的开源博客系统&#xff0c;以其简单易用、功能强大、美观大方等特点而受到广泛欢迎&#xff0c;采用了多种先进的技术框架&#xff0c;包括Freemarker模板引擎、Vue.j…...

Android carrier_list.textpb 和apns-conf.xml 配置文件参考

简介 针对SIM 的APN配置是在apns-conf.xml,而Google源码中有apns-full-conf.xml案例参考,是加入了carrier_id的统一配置,就不用单独的一张张卡配了。 apns-conf.xml和apns-full-conf.xml有什么区别? 在于它们包含的配置内容和复杂性,full包含了carrier_id字段。 详细代…...

二期 1.4 Nacos安装部署 - Window版

本文目录 Nacos支持三种部署模式环境准备下载Nacos启动登录服务注册与查看Nacos支持三种部署模式 单机模式 - 用于测试和单机试用。集群模式 - 用于生产环境,确保高可用。多集群模式 - 用于多数据中心场景。以 Window单机模式 抛转引玉,其它部署方式参考官方文档: https://n…...

vue3基础九问,你会几问

1. Vue是什么&#xff1f; Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它的核心库只关注视图层&#xff0c;采用自下而上的增量开发设计&#xff0c;这使得你可以将 Vue 轻松地整合到现有的项目中&#xff0c;或者与其他前端库一起使用。Vue 的目标是通过提供反…...

Linux系统应用之知识补充——OpenEuler(欧拉)的安装和基础配置

前言 这篇文章将会对OpenEuler的安装进行详解&#xff0c;一步一步跟着走下去就可以成功 注意 &#xff1a;以下的指令操作最好在root权限下进行&#xff08;即su - root&#xff09; ☀️工贵其久&#xff0c;业贵其专&#xff01; 1、OpenEuler的安装 这里我不过多介绍&a…...

Git(4):修改git提交日志

修改最新一次提交的信息 git commit --amend 修正提交信息 在打开的编辑器中修改信息&#xff0c;保存并退出&#xff0c;Git 会用新的提交信息替换掉旧的提交信息&#xff08;commit-id 变化&#xff09;。也可以使用 git commit --amend -m "" 直接修改日志&#…...

【深度学习】(1)--神经网络

文章目录 深度学习神经网络1. 感知器2. 多层感知器偏置 3. 神经网络的构造4. 模型训练损失函数 总结 深度学习 深度学习(DL, Deep Learning)是机器学习(ML, Machine Learning)领域中一个新的研究方向。 从上方的内容包含结果&#xff0c;我们可以知道&#xff0c;在学习深度学…...

测试文件和数据库文件

接口测试 flaks项目入口文件manage.py路由配置 import requests#首先面向对象作封装&#xff0c;避免相同代码反复编写 class HttpApiTest:def test_get(self,url,data{}): #用来测试get方法的接口 #self通过共享self类中间的变量 #url用来请求接口 #data可传可不传res reques…...

redis集群模式连接

目录 一&#xff1a;背景 二&#xff1a;实现过程 三&#xff1a;总结 一&#xff1a;背景 redis集群通过将数据分散存储在多个主节点上&#xff0c;每个主节点可以有多个从节点进行数据的复制&#xff0c;以此来实现数据的高可用性和负载均衡。在集群模式下&#xff0c;客户…...

Linux高级I/O:多路转接模型

目录 一.常见的IO模型介绍二.多路转接I/O1.select1.1.函数解析1.2. select特点和缺点1.3.基于 select 的多客户端网络服务器 2.poll2.1.poll函数解析2.2.poll特点和缺点2.3.基于poll的tcp服务器 3.epoll3.1.系列函数解析3.2.epoll原理解析2.3.基于 select 的多客户端网络服务器…...

MongoDB Limit 与 Skip 方法

MongoDB Limit 与 Skip 方法 MongoDB 是一个流行的 NoSQL 数据库&#xff0c;它提供了灵活的数据存储和强大的查询功能。在处理大量数据时&#xff0c;我们常常需要限制返回的结果数量或者跳过一部分结果&#xff0c;这时就可以使用 MongoDB 的 limit 和 skip 方法。 Limit 方…...

【2025】中医药健康管理小程序(安卓原生开发+用户+管理员)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…...

VulnHub-Bilu_b0x靶机笔记

Bilu_b0x 靶机 概述 Vulnhub 的一个靶机&#xff0c;包含了 sql 注入&#xff0c;文件包含&#xff0c;代码审计&#xff0c;内核提权。整体也是比较简单的内容&#xff0c;和大家一起学习 Billu_b0x.zip 靶机地址&#xff1a; https://pan.baidu.com/s/1VWazR7tpm2xJZIGUS…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

机器学习的数学基础:线性模型

线性模型 线性模型的基本形式为&#xff1a; f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法&#xff0c;得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...

CSS3相关知识点

CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

工厂方法模式和抽象工厂方法模式的battle

1.案例直接上手 在这个案例里面&#xff0c;我们会实现这个普通的工厂方法&#xff0c;并且对比这个普通工厂方法和我们直接创建对象的差别在哪里&#xff0c;为什么需要一个工厂&#xff1a; 下面的这个是我们的这个案例里面涉及到的接口和对应的实现类&#xff1a; 两个发…...