【C++】—— C++11新特性之 “右值引用和移动语义”
前言:
- 本期,我们将要的介绍有关 C++右值引用 的相关知识。对于本期知识内容,大家是必须要能够掌握的,在面试中是属于重点考察对象。
目录
(一)左值引用和右值引用
1、什么是左值?什么是左值引用?
2、什么是右值?什么是右值引用?
(二)左值引用与右值引用比较
(三)右值引用使用场景和意义
(四)完美转发
1、概念
2、模板中的&& 万能引用
3、std::forward
总结
(一)左值引用和右值引用
传统的C++语法中就有引用的语法,而C++11中新增了的右值引用语法特性,所以从现在开始我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用,都是给对象取别名。
1、什么是左值?什么是左值引用?
C++98/03 标准中就有引用,使用 "&" 表示。但此种引用方式有一个缺陷,即正常情况下只能操作 C++中的左值,无法对右值添加引用。举个例子:
int main()
{int num = 10;int& b = num; //正确int& c = 10; //错误return 0;
}
输出展示:
【解释说明】
- 如上所示,编译器允许我们为 num 左值建立一个引用,但不可以为 10 这个右值建立引用。因此,C++98/03 标准中的引用又称为左值引用。
那么到底什么是左值?什么是左值引用呢?
- 左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边;
- 定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名。
注意:虽然 C++98/03 标准不支持为右值建立非常量左值引用,但允许使用常量左值引用操作右值。也就是说,常量左值引用既可以操作左值,也可以操作右值,例如:
int main()
{// 以下的p、b、c、*p都是左值int* p = new int(0);int b = 1;const int c = 2;// 以下几个是对上面左值的左值引用int*& rp = p;int& rb = b;//左值引用给右值取别名const int& rc = c;int& pvalue = *p;return 0;
}
2、什么是右值?什么是右值引用?
我们知道,右值往往是没有名称的,因此要使用它只能借助引用的方式。这就产生一个问题,实际开发中我们可能需要对右值进行修改(实现移动语义时就需要),显然左值引用的方式是行不通的。
为此,C++11 标准新引入了另一种引用方式,称为右值引用,用 "&&" 表示:
- 右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引用返回)等等;
- 右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址;
- 右值引用就是对右值的引用,给右值取别名。
int main()
{double x = 1.1, y = 2.2;// 以下几个都是常见的右值10;x + y;fmin(x, y);// 以下几个都是对右值的右值引用int&& rr1 = 10;double&& rr2 = x + y;double&& rr3 = fmin(x, y);return 0;
}
输出展示:
但是如果是下面这几个表达式,就会发生报错现象:
10 = 1;
x + y = 1;
fmin(x, y) = 1;
输出显示:
需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可
以取到该位置的地址。例如下面代码所示:
int main()
{double x = 1.1, y = 2.2;int&& rr1 = 10;double&& rr2 = x + y;cout << rr1 << " " << rr2 << " " << endl;rr1 = 20;rr2 = 5.5;cout << rr1 << " " << rr2 << " " << endl;return 0;
}
输出展示:
当我们不想被修改时,我们可以加上 【const】关键字:
【解释说明】
- 不能取字面量10的地址,但是rr1引用后,可以对rr1取地址,也可以修改rr1;
- 如果不想rr1被修改,可以用const int&& rr1 去引用;
- 是不是感觉很神奇这个了解一下实际中右值引用的使用场景并不在于此,这个特性也不重要
(二)左值引用与右值引用比较
左值引用总结:
- 1. 左值引用只能引用左值,不能引用右值。
- 2. 但是const左值引用既可引用左值,也可引用右值
int main()
{// 左值引用只能引用左值,不能引用右值。int a = 10;int& ra1 = a; // ra为a的别名return 0;
}
输出展示:
又例如以下示例:
int main()
{// 左值引用只能引用左值,不能引用右值。int a = 10;int& ra2 = 10; // 编译失败,因为10是右值return 0;
}
输出展示:
左值引用只能引用左值,不能引用右值。但是当我们加上 const 时,此时左值引用可以给右值取别名:
int main()
{int a = 10;// const左值引用既可引用左值,也可引用右值。const int& ra3 = 10;const int& ra4 = a;return 0;
}
输出展示:
【解释说明】
值得一提的是,虽然C++ 语法上是支持定义常量右值引用的,但这种定义出来的右值引用并无实际用处:
const int& ra3 = 10;
- 一方面,右值引用主要用于移动语义和完美转发,其中前者需要有修改右值的权限;
- 其次,常量右值引用的作用就是引用一个不可修改的右值,这项工作完全可以交给常量左值引用完成。
右值引用总结:
- 1. 右值引用只能右值,不能引用左值。
- 2. 但是右值引用可以move以后的左值。
代码展示:
引用左值会发生报错行为:
通过 move 可以支持将左值转换为右值引用
在C++中,move
是一个函数模板,可以将给定的对象转换为对应的右值引用。它并不执行实际的内存移动操作,而是将对象标记为可以进行移动操作的右值。这样,用户可以利用该标记来实现更高效的移动语义。
(三)右值引用使用场景和意义
前面我们可以看到左值引用既可以引用左值和又可以引用右值,那为什么C++11还要提出右值引用呢?是不是化蛇添足呢?下面我们来看看左值引用的短板,右值引用是如何补齐这个短板的!
现有以下代码:
【解释说明】
首先,对于上述代码中的 res1 和 res2 ,它们分别为左值和右值;
紧接着大家想想,我们对左值和对右值拷贝有没有什么区别呢?
- 如果是内置类型,他们其实区别不是很大,但是对于自定类型他们的区别可就很大了,
- 因为自定义类型的右值,一般很多地方又把它叫做将亡值。通常都是一些表达式的返回值、一个函数调用等;
- 而对于右值又分为 纯右值(一般来说是内置类型)和将亡值(一般来说是自定义类型)
对于上述的 res1,它作为一个左值,我们不能对其进行操作,只能去做深拷贝。因为虽然看起来这里是一个赋值,其实应该是拷贝构造;
而对于 res2 来说,它本身是右值,假如是自定义类型作为一个将亡值,我们就没有必要去对其进行拷贝操作。此时就引出了关于右值引用实现引动构造的概念。
例如现在有这样一个我们手写模拟的 string :
namespace zp
{class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}string(const char* str = ""):_size(strlen(str)), _capacity(_size){//cout << "string(char* str)" << endl;_str = new char[_capacity + 1];strcpy(_str, str);}// s1.swap(s2)void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}// 拷贝构造string(const string& s):_str(nullptr){cout << "string(const string& s) -- 深拷贝" << endl;string tmp(s._str);swap(tmp);}// 赋值重载string& operator=(const string& s){cout << "string& operator=(string s) -- 深拷贝" << endl;string tmp(s);swap(tmp);return *this;}~string(){delete[] _str;_str = nullptr;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void push_back(char ch){if (_size >= _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}//string operator+=(char ch)string& operator+=(char ch){push_back(ch);return *this;}string operator+(char ch){string tmp(*this);tmp += ch;return tmp;}const char* c_str() const{return _str;}private:char* _str;size_t _size;size_t _capacity; // 不包含最后做标识的\0};
}
当我们再这样的场景在来观察上述的 res1 和res2:
我们可以发现此处的右值发生的是相应的深拷贝,这样显然是会造成不必要的浪费的。为了解决上述这样的问题,我们就可以引入 “移动构造” 这样的概念:
// 移动构造
string(string&& s):_str(nullptr)
{cout << "string(string&& s) -- 移动拷贝" << endl;swap(s);
}
紧接着,再次运行上述代码,我们可以发现编译器会去自动识别:
此时,当我们就是想把 s1 转为右值可以怎么做呢?其实很简单(这里就体现了move):
输出展示:
我们通过调试也可以发现此时确实达到了预期的效果:
【小结】
通过上述我们可以发现左值引用的好处就是直接减少拷贝
左值引用的使用场景可以分为以下两个部分:
- 做参数和做返回值都可以提高效率
左值引用的短板:
- 但是当函数返回对象是一个局部变量,出了函数作用域就不存在了,就不能使用左值引用返回,只能传值返回。
例如现在有以下这样的代码:
zp::string to_string(int value){bool flag = true;if (value < 0){flag = false;value = 0 - value;}zp::string str;while (value > 0){int x = value % 10;value /= 10;str += ('0' + x);}if (flag == false){str += '-';}std::reverse(str.begin(), str.end());return str;}
【说明】
- zp::string to_string(int value)函数中可以看到,这里只能使用传值返回,传值返回会导致至少1次拷贝构造(如果是一些旧一点的编译器可能是两次拷贝构造)。
紧接着,我们去打印看结果是什么:
此时,传值返回带来的代价得到了极大的解决:
右值引用和移动语义解决上述问题:
- 在zp::string中增加移动构造,移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己;
再运行上面zp::to_string的两个调用,我们会发现,这里没有调用深拷贝的拷贝构造,而是调用了移动构造,移动构造中没有新开空间,拷贝数据,所以效率提高了。
c++11 不仅仅有移动构造,还有移动赋值:
在zp::string类中增加移动赋值函数,再去调用zp::to_string(1234),不过这次是zp::to_string(1234)返回的右值对象赋值给ret1对象,这时调用的是移动构造。
输出展示:
【解释说明】
- 这里运行后,我们看到调用了一次移动构造和一次移动赋值。因为如果是用一个已经存在的对象接收,编译器就没办法优化了。zp::to_string函数中会先用str生成构造生成一个临时对象,但是我们可以看到,编译器很聪明的在这里把str识别成了右值,调用了移动构造。然后在把这个临时对象做为 zp::to_string 函数调用的返回值赋值给ret1,这里调用的移动赋值。
(四)完美转发
1、概念
- 完美转发(perfect forwarding)是C++11引入的一项特性,旨在实现在函数模板中对参数类型进行精确传递的能力;
- 它主要用于保留传递到函数模板的实参的值类别,并将其转发到内部调用的函数,从而实现类型和值类别的完全保持;
举个例子:
template<typename T>
void PerfectForward(T t)
{Fun(t);
}
【解释说明】
- 如上所示,PerfectForward() 函数模板中调用了 Func() 函数;
- 在此基础上,完美转发指的是:如果 PerfectForward() 函数接收到的参数 t 为左值,那么该函数传递给 Func() 的参数 t 也是左值;
- 反之如果 function() 函数接收到的参数 t 为右值,那么传递给 Func() 函数的参数 t 也必须为右值。
使用任何一种引用形式,可以实现转发,但无法保证完美。因此如果使用 C++ 98/03 标准下的 C++ 语言,我们可以采用函数模板重载的方式实现完美转发,例如:
template<typename T>
void Func(T& arg)
{cout << "左值引用:" << arg << endl;
}template<typename T>
void Func(T&& arg)
{cout << "右值引用:" << arg << endl;
}template<typename T>
void PerfectForward(T&& arg)
{Func(arg); // 利用重载的process函数进行处理
}int main()
{int value = 42;PerfectForward(value); // 传递左值PerfectForward(123); // 传递右值return 0;
}
输出展示:
【解释说明】
- 在上述示例中,我们定义了两个重载的函数模板
Func
,一个接收左值引用参数T& arg
,另一个接收转发引用参数T&& arg;
- 然后,我们再定义一个模板函数
PerfectForward
,其参数也是转发引用T&& arg
。在PerfectForward
函数内部,我们通过调用Func
函数来处理传递的参数; - 通过函数重载的机制,传递的左值参数将匹配到接收左值引用的
Func
函数,传递的右值参数则匹配到接收转发引用的Func
函数,从而正确地进行区分和处理; - 通过函数模板的重载,我们可以根据参数类型将左值和右值区分开来,并分别处理,实现了针对不同值类别的精确匹配和操作。
2、模板中的&& 万能引用
显然,上述使用重载的模板函数实现完美转发也是有弊端的,此实现方式仅适用于模板函数仅有少量参数的情况,否则就需要编写大量的重载函数模板,造成代码的冗余。为了方便用户更快速地实现完美转发,C++ 11 标准中允许在函数模板中使用右值引用来实现完美转发。
还是以 PerfectForward() 函数为例,在 C++11 标准中实现完美转发,只需要编写如下一个模板函数即可:
//模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。
template<typename T>
void PerfectForward(T&& t)
{Fun(t);
}
以如下代码为例:
void Fun(int& x)
{ cout << "左值引用" << endl;
}
void Fun(const int& x)
{cout << "const 左值引用" << endl;
}
void Fun(int&& x)
{cout << "右值引用" << endl;
}
void Fun(const int&& x)
{cout << "const 右值引用" << endl;
}template<typename T>
void PerfectForward(T&& t)
{Fun(t);
}
int main()
{PerfectForward(10); // 右值int a;PerfectForward(a); // 左值PerfectForward(std::move(a)); // 右值const int b = 8;PerfectForward(b); // const 左值PerfectForward(std::move(b)); // const 右值return 0;
}
输出展示:
【解释说明】
- 模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。
- 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力,
- 但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值,
- 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
3、std::forward
C++11 标准的开发者已经帮我们想好的解决方案,该新标准还引入了一个模板函数 forword<T>(),我们只需要调用该函数,就可以很方便地解决此问题。
- 完美转发通常与转发引用(forwarding reference)和 std::forward 函数一起使用;
- 转发引用是一种特殊的引用类型,使用
&&
语法进行声明,用于在函数模板中捕获传递的实参; - std::forward 是一个模板函数,用于在函数模板内部将转发引用作为右值或左值引用进行转发。
如下演示了该函数模板的用法:
void Fun(int& x)
{ cout << "左值引用" << endl;
}
void Fun(const int& x)
{cout << "const 左值引用" << endl;
}
void Fun(int&& x)
{cout << "右值引用" << endl;
}
void Fun(const int&& x)
{cout << "const 右值引用" << endl;
}template<typename T>
void PerfectForward(T&& t)
{// forward<T>(t)在传参的过程中保持了t的原生类型属性。Fun(std::forward<T>(t));
}
int main()
{PerfectForward(10); // 右值int a;PerfectForward(a); // 左值PerfectForward(move(a)); // 右值const int b = 8;PerfectForward(b); // const 左值PerfectForward(move(b)); // const 右值return 0;
}
程序执行结果为:
通过完美转发,我们可以在函数模板中正确处理传递实参的值类别,并将其转发到内部函数,以达到类型和值类别的完全保持,提高代码的灵活性和效率。
总结
学到这里,一些读者可能无法记清楚左值引用和右值引用各自可以引用左值还是右值,这里给大家一张表格,方便大家记忆:
- 表中,Y 表示支持,N 表示不支持。
以上便是关于左值引用和右值引用的全部知识讲解!感谢大家的观看与支持!!!
相关文章:
【C++】—— C++11新特性之 “右值引用和移动语义”
前言: 本期,我们将要的介绍有关 C右值引用 的相关知识。对于本期知识内容,大家是必须要能够掌握的,在面试中是属于重点考察对象。 目录 (一)左值引用和右值引用 1、什么是左值?什么是左值引用…...
谈一谈redis脑裂
什么是redis脑裂 (1)一主多从架构中,主节点与客户端通信正常,主节点与哨兵、从节点连接异常,客户端仍正常写入数据 (2)哨兵判定主节点下线,重新选主 (3)原主…...
基于原生Servlet使用模板引擎Thymeleaf访问界面
我们常在Spring Boot项目中使用Thymeleaf模板引擎,今天突发奇想,尝试原生Servlet访问! 说做就做 搭建完整的WEB项目 其中的大部分依赖都是后续报错 追加进来的 导入依赖 thymeleaf-3.0.11.RELEASE.jar 第一次访问 访问地址: http://localhost:8080…...
【C语言】15-函数-1
1. 初步认识函数 通过前几章的学习,已经可以编写一些简单的 C 语言程序了,但是如果程序的功能比较多,规模比较大,把所有的程序代码都写在一个主函数(main函数)中,就会使主函数变得庞杂、头绪不清,使阅读和维护程序变得困难。此外,有时程序中要多次实现某一功能就需要…...
08-信息收集-架构、搭建、WAF等
信息收集-架构、搭建、WAF等 信息收集-架构、搭建、WAF等一、前言说明二、CMS识别技术三、源码获取技术四、架构信息获取技术五、站点搭建分析1、搭建习惯-目录型站点2、搭建习惯-端口类站点3、搭建习惯-子域名站点4、搭建习惯-类似域名站点5、搭建习惯-旁注,c段站点…...
Qt --- 显示相关设置 窗口属性等
主界面,窗口 最小化 最大化 关闭按钮、显示状态自定义: setWindowFlags(Qt::CustomizeWindowHint); setWindowFlags(Qt::WindowCloseButtonHint); //只要关闭按钮 setWindowFlags(Qt::WindowFlags type) Qt::FrameWindowHint:没有边框的窗口 Qt::Window…...
使用小程序实现左侧菜单,右侧列表双向联动效果
目录 引言理解双向联动效果的重要性scrollview属性介绍实现左侧菜单数据准备渲染菜单列表监听菜单点击事件实现右侧列表数据结构设计初始数据渲染监听列表滚动事件左侧菜单与右侧列表联动获取当前滚动位置计算对应菜单项联动效果优化用户体验考虑平滑滚动效果菜单高亮状态...
selenium中处理验证码问题
验证码 基本作用:可以实现当前访问页面的数据安全性、还可以减少用户的并发数; 类型:1、纯数字、纯字母;2、汉字组合;3、数学运算题;4、滑动;5、图片(选不同的、选相同、成语顺序&…...
EMR电子病历系统 SaaS电子病历编辑器源码 电子病历模板编辑器
EMR(Electronic Medical Record)指的是电子病历。它是一种基于电子文档的个人医疗记录,可以包括病人的病史、诊断、治疗方案、药物处方、检查报告和护理计划等信息。EMR采用计算机化的方式来存储、管理和共享这些信息,以便医生和医…...
一些自定义hooks
文章目录 1、点击框外隐藏弹窗hook 1、点击框外隐藏弹窗hook **描述:**有一个需要自己封装弹窗的组件,实现点击弹窗框外时隐藏弹窗 代码: import { useEffect } from “react”; // 点击框外hooks import { useEffect } from "react&q…...
基于Citespace、vosviewer、R语言的文献计量学可视化分析技术及全流程文献可视化SCI论文高效写作方法
文献计量学是指用数学和统计学的方法,定量地分析一切知识载体的交叉科学。它是集数学、统计学、文献学为一体,注重量化的综合性知识体系。特别是,信息可视化技术手段和方法的运用,可直观的展示主题的研究发展历程、研究现状、研究…...
lEC 61068-2-14_2023环境试验.第2-14部分:试验.试验N:温度变化, 最新版发布
https://download.csdn.net/download/m0_67373485/88251313 lEC 61068-2-14_2023环境试验.第2-14部分:试验.试验N:温度变化 A change of temperature test is intended to determine the effect on the specimen of a changeof temperature or a succession of changes of tem…...
CFDEM学习笔记
本文用来记录自己学习CFDEM的笔记。 资料总结 虚拟机:链接:https://pan.baidu.com/s/1MPMTJQfl76mW0H5bbT_rAg 提取码:rqli 开机密码:530944988 知乎博客:作者说明了如何关闭颗粒碰撞计算来达到提升计算速度。 Githu…...
SpringBoot入门篇1 - 简介和工程创建
目录 SpringBoot是由Pivotal团队提供的全新框架, 其设计目的是用来简化Spring应用的初始搭建以及开发过程。 1.创建入门工程案例 ①创建新模块,选择Spring初始化,并配置模块相关基础信息 ②开发控制器类 controller/BookController.jav…...
MyBatis-Plus updateById不更新null值
文章目录 前言方式一 调整全局的验证策略方式二 调整字段验证注解方式三 使用 UpdateWrapper 前言 在 MyBatis-Plus 中,使用updateById,null字段并不会更新,其实是和更新的策略有关,当然,也有插入策略,本文…...
用pytorch实现AlexNet
AlexNet经典网络由Alex Krizhevsky、Hinton等人在2012年提出,发表在NIPS,论文名为《ImageNet Classification with Deep Convolutional Neural Networks》,论文见:http://www.cs.toronto.edu/~hinton/absps/imagenet.pdf …...
LeetCode560.和为k的子数组
这道题我用的是暴力法,当然也是不断的提交不断发现问题改出来的,比如我之前是算到和大于目标值就break,其实不行因为后面还可以有负数,我把break删了。后面和为目标之后就答案1然后break然后下一次遍历,测试用例中就出…...
echarts 的dataZoom滑块两端文字被遮挡
问题: 期望: 解决方案: 1:调整宽度(4版本的没有width属性) 2. 参考:echarts图标设置dataZoom拖拽时间轴时自动调整两侧文字的位置_datazoom 位置_乌栖曲的博客-CSDN博客 设置文字的定位 cons…...
MongoDB基本使用
在 MongoDB 中我们可以使用use命令来创建数据库,如果该数据库不存在,则会创建一个新的数据库,如果该数据库已经存在,则将切换到该数据库。使用use命令创建数据库的语法格式如下: --use database_name use my_db1;数据…...
C++ 中的左值(Lvalues)和右值(Rvalues)
C 中有两种类型的表达式: 左值(lvalue):左值参数是可被引用的数据对象,例如,变量、数组元素、结构成员、引用和解除引用的指针都是左值。非左值包括字面常量(用引号起的字符串除外,…...
html流光按钮
出处bilibili猫咪爱狗 <!DOCTYPE html> <html><head><style>body {/*内容居中,背景色*/height: 100vh;display: flex;justify-content: center; align-items: center;background-color: #000;}a { /*水平垂直居中*/position: re…...
HAProxy+nginx搭建负载均衡群集
目录 一、常见的Web集群调度器 二、HAProxy群集介绍 1、Haproxy的特性 : 2、Haproxy常用的调度算法 ① 轮询调度(Round Robin) ② 最小连接数(Least Connections) ③ 基于来源访问调度算法(Source Hashing&am…...
logback-spring.xml 的配置及详解(直接复制粘贴可用)
logback-spring.xml 的配置及详解 一、注意实现二、配置及详解 一、注意实现 logback-spring.xml 中有三处需要根据实际业务进行修改,直接查找“(根据业务修改)”即可进行定位。 如果不想修改,直接复制粘贴到自己系统运行也可以&…...
C语言易错点整理
前言: 本文涵盖了博主在平常写C语言题目时经常犯的一些错误,在这里帮大家整理出来,一些易错点会帮大家标识出来,希望大家看完这篇文章后有所得,引以为戒~ 一、 题目: 解答: 首先在这个程序中…...
60.每日一练:回文数(力扣)
目录 问题描述 代码解决以及思想 解法(一) 知识点 解法(二) 问题描述 代码解决以及思想 解法(一) class Solution { public:bool isPalindrome(int x) {string arr to_string(x); // 将整数转换为…...
算法通关村第5关【青铜】| Hash和队列的特征
1.Hash基础 (1)基础 哈希也称为散列,通过算法变成固定长度的输出值,存入对应的位置 例如这个算法为取模算法,indexnumber 模 7 存入1到15 (2)碰撞处理 当多个元素映射到同一位置上时就产生…...
C++:函数
函数参数的传递机制 C的每个程序至少有一个函数,即主函数main(),函数也是类的方法的实现手段。C的函数包括两类:预定于函数和用户自定义函数。 函数的定义格式为: <返回值类型><函数名>(<参数列表>) <函…...
Linux网络编程:libevent事件通知库
文章目录: 一:libevent库 二:libevent框架 1.常规事件event 1.1 创建事件event(event_new) 1.2 添加事件到 event_base(event_add) 1.3 从event_base上摘下事件(event_del&a…...
java.lang.reflect.InvocationTargetException:null报未知异常
在项目上线过程中,突然出现大量异常信息,堆栈信息如下: java.lang.reflect.InvocationTargetException: null at jdk .internal.reflect.GeneratedMethodAccessor792 .invoke(Unknown Source) ~[?:?] at jdk.internal.reflect.DelegatingM…...
MySQL高级篇——MySQL架构篇1(Linux下MySQL8的安装与使用)
目录 0 安装前0.1 Linux系统及工具的准备0.2 查看是否安装过MySQL0.3 MySQL的卸载 1 MySQL8的Linux版安装1.1 MySQL的4大版本1.2 下载MySQL指定版本1.3 CentOS7下检查MySQL依赖1.4 CentOS7下MySQL安装过程 2 MySQL登录2.1 首次登录2.2 修改密码2.3 设置远程登录 3 MySQL 8 的密…...
wordpress搭建后域名打不开/百度教育
//分支语句可以嵌套 //循环语句,同样可以嵌套 例一: //打印三角形:左下角是直角 Console.Write("请输入一个正整数:"); int a int.Parse(Console.ReadLine()); for (int i …...
腾讯网页游戏排行榜/朝阳区seo搜索引擎优化怎么样
在Android系统中用来显示界面的组件(Component)为Activity,也就是说只有重写Activity的onKeyDown方法来监控/拦截/屏蔽系统的返回键(back)、菜单键(Menu)及Home键。 1、拦截/屏蔽返回键、菜单键…...
免费门户网站建设/短网址生成器免费
1. WebSocket编程 文章目录1. WebSocket编程1.1.1. webSocket是什么1.1.2. 举个聊天室的小例子server.go文件代码hub.go文件代码data.go文件代码local.html文件代码1.1.1. webSocket是什么 WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户端和服务器之…...
天津企业网站/武汉seo关键词排名优化
配置主配置文件用vi或其它文件编辑器编辑主配置文件httpd.conf : vi /usr/local/apache-2.2.6/conf/httpd.conf 按下面提示进行修改:###httpd.conf begin##Apache主配置文件##设置服务器的基础目录,默认为Apache安装目录ServerRoot "/…...
国内做网站最好的公司/免费发布软文广告推广平台
PHP获取毫秒级时间戳的方法本文实例讲述了PHP获取毫秒级时间戳的方法。分享给大家供大家参考。具体分析如下:PHP本身没有提供获取毫秒级时间戳的函数,java里面可以通过gettime();获取。如果是要与java写的某些程序进行高精度的毫秒级的对接通信ÿ…...
php网站建设流程/学seo如何入门
前段时间的帖子,利用TPYBoard v102做的DIY照相机,周末实物终于做出来了,加了两个按键模块和一个5110,做的有点糙啊----望大家勿怪,哈哈哈。拍出来图片还算清晰,串口摄像头模块用的30w像素的(贫穷…...