《C++ Primer》 第十二章 动态内存
《C++ Primer》 第十二章 动态内存
动态内存与智能指针
shared_ptr允许多个指针指向同一个对象;unique_ptr则“独占”所指向的对象,weak_ptr指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。
shared_ptr类:默认初始化的智能指针中保存着一个空指针。
shared_ptr<string> p1; //shared_ptr,可以指向string
shared_ptr<list<int>> p2; //shared_ptr, 可以指向int的list//如果p1不为空,检测它是否指向一个空string
if(p1 && p1->empty())*p1 = "hi";//如果p1指向一个空string,解引用p1,将一个新值赋予string
make_shared函数:在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。定义在memory中。
//指向一个值为42的int的shared_ptr
shared_ptr<int> p3 = make_shared<int> (42);
//p4指向一个值为"999999999"的string
shared_ptr<string> p4 = make_shared<string> (10,'9');
//p5指向一个值初始化的int,即值为0
shared_ptr<int> p5 = make_shared<int>();
//通常使用auto定义一个对象来保存make_shared的结果
//p6指向一个动态分配的空vector<string>
auto p6 = make_shared<vector<string>>();
shared_ptr的拷贝和构造:
auto p = make_shared<int>(42);//p指向的对象只有一个引用者
auto q(p);//p和q指向相同对象,此对象有两个引用者
定义StrBlob类:
class StrBlob{
public:typedef std::vector<std::string>::size_type size_type;StrBlob();StrBlob(std::initializer_list<std::string> i1);size_type size() const { return data->size(); }bool empty() const { return data->empty(); }//添加和删除元素void push_back(const std::string &t) { data->push_back(t); }void pop_back();//元素访问std::string& front();std::string& back();
private:std::shared_ptr<std::vector<std::string>> data;//如果data[i]不合法,抛出一个异常void check(size_type i, const std::string &msg) const;
};
元素访问成员函数:
void StrBlob::check(size_type i, const string &msg) const
{if(i>=data->size())throw out_of_range(msg);
}string& StrBlob::front()
{//如果vector为空,check会抛出一个异常check(0, "front on empty StrBlob");
}string& StrBlob::back()
{check(0, "back on empty StrBlob");return data->back();
}void StrBlob::pop_back()
{check(0, "pop_back on empty StrBlob");data->pop_back();
}
直接管理内存:运算符new分配内存,delete释放new分配的内存。
使用new动态分配和初始化对象:new返回一个指向该对象的指针
int *pi = new int; //pi指向一个动态分配、并返回该对象的指针string *ps = new string;//初始化为空string
int *pi = new int;//pi指向一个未初始化的intint *pi = new int(1024);//pi指向的对象的值是1024
string *ps = new string(10,'9'); //*ps为“999999999”//vector有10个元素,值依次从0~9
vector<int> *pv = new vector<int> {0,1,2,3,4,5,6,7,8,9};string *ps1 = new string;//默认初始化为空string
string *ps = new string();//值初始化为空string
int *pi1 = new int; //默认初始化;*pi1的值未定义
int *pi2 = new int();//值初始化为0;*pi2为0auto p1 = new auto(obj); //p指向一个与obj类型相同的对象,该对象用obj进行初始化
auto p2 = new auto{a,b,c};//错误:括号中只能有单个初始化器
动态分配的const对象:用new分配const对象是合法的:
//分配并初始化一个const int
const int *pci = new const int(1024);
//分配并默认初始化一个const的空string
const string *pcs = new const string;
内存耗尽:
//如果分配失败,new返回一个空指针
int *p1 = new int;//如果分配失败,new抛出std::bad_alloc
int *p2 = new (nothrow) int;//如果分配失败,new返回一个空指针
释放动态内存:销毁给定的指针指向的对象;释放对应的内存。
delete p;//p必须指向一个动态分配的对象或是一个空指针
指针值和delete:传递给delete的指针必须指向动态分配的内存,或者是一个空指针。
int i, *pi1 = &i, &pi2 = nullptr;
double *pd = new double(33), *pd2 = pd;
delete i;//错误:i不是一个指针
delete pi1;//未定义:pi1指向一个局部变量
delete pd;//正确
delete pd2;//未定义:pd2指向的内存已经被释放掉了
delete pi2;//正确:释放一个空指针总是没有错误的const int *pci = new const int(1024);
delete pci;//正确:释放一个const对象
动态对象的生存期直到被释放时为止:
//factory返回一个指针,指向一个动态分配的对象
Foo* factory(T arg)
{//视情况处理argreturn new Foo(arg);//调用者负责释放此内存
}void use_factory(T arg)
{Foo *p = factory(arg);//使用p但不delete它
}//p离开了它的作用域,但它所指向的内存没有被释放!!!void use_factory(T arg)
{Foo *p = factory(arg);//使用pdelete p;//现在记得释放内存,我们已经不需要它了
}Foo* use_factory(T arg)
{Foo *p = factory(arg);//使用preturn p;//调用者必须释放内存
}
提供优先的保护:动态内存的一个基本问题是可能有多个指针指向相同的内存。
int *p (new int(42));//p指向动态内存
auto q = p; //p和q指向相同的内存
delete p; //p和q均变为无效
p = nullptr; //指出p不再绑定到任何对象
shared_ptr和new结合使用:
shared_ptr<double> p1;//shared_ptr可以指向一个double
shared_ptr<int> p2(new int(42));//p2指向一个值为42的int//不能将一个内置指针隐式转换为一个智能指针
shared_ptr<int> p1 = new int(1024);//错误:必须使用直接初始化形式
shared_ptr<int> p2(new int(1024));//正确:使用了直接初始化形
不能进行内置指针到智能指针间的隐式转换。一个返回shared_ptr的函数不能在其返回语句中隐式转换为一个普通指针:
shared_ptr<int> clone(int p){return new int(p);//错误:隐式转换为shared_ptr<int>
}//必须将shared_ptr显式绑定到一个想要返回的指针上
shared_ptr<int> clone(int p){//正确:显示地用int*创建shared_ptr<int>return shared_ptr<int>(new int(p));
}
不要混合使用普通指针和智能指针;也不要使用get初始化另一个智能指针或为智能指针赋值。
shared_ptr<int> p(new int(42));//引用计数为1
int *q = p.get();//正确,但使用q时要注意,不要让它管理的指针被释放
{//新程序块
//未定义:两个独立的shared_prt指向相同的内存shared_ptr<int>(q);
}//程序块结束,q被销毁,它指向的内存本释放
int foo = *p; //未定义:p指向的内存已经被释放了
其它shared_ptr操作:
p = new int(1024); //错误:不能将一个指针赋予shared_ptr
p.reset(new int(1024)); //正确:p指向一个新对象if(!p.unique())p.reset(new string(*p));//我们不是唯一用户;分配新的拷贝
*p += newVal;
智能指针和异常:
void f()
{shared_ptr<int> sp(new int(42));//分配一个新对象//这段代码抛出一个异常,且在f中未被捕获
}//在函数结束时shared_ptr自动释放内存void f()
{int *p = new int(42);//动态分配一个新对象//这段代码抛出一个异常,且在f中未被捕获delete ip;//退出之前释放内存
}
智能指针和哑类“
struct destination;//表示我们正在连接什么
struct connection;//使用连接所需的信息
connection connect(destination*);//打开连接
void disconnect(connection);//关闭给定的连接
void f(destination &d)
{//获得一个连接;记住使用玩后要关闭它connection c = connect(&d);//使用连接//如果我们在f退出之前忘记调用disconnect,就无法关闭c了
}//在创建shared_ptr时,可以传递一个可选的指向删除器函数的参数
void f(destination &d)
{//获得一个连接;记住使用玩后要关闭它connection c = connect(&d);shared_ptr<connection> p(&c, end_connection);//使用连接//如果我们在f退出之前忘记调用disconnect,就无法关闭c了
}
unique_ptr:与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定对侠女。当unique_ptr被销毁时,它所指向的对象也被销毁。
unique_ptr<double> p1;//可以指向一个douvbble的unique_ptr
unique_ptr<int> p2(new int(42));//p2指向一个值为42的int
//由于一个unique_ptr拥有它指向的对象,因此unique_ptr不支持普通的拷贝或赋值操作
unique_ptr<string> p1(new string("Stegosaurus"));
unique_ptr<string> p2(p1);//错误:unique_ptr不支持拷贝
unique_ptr<string> p3;
p3 = p1;//错误:unique_ptr不支持赋值
使用unique_ptr参数和返回unique_ptr
unique_ptr<int> clone(int p){//正确:从int*创建一个unique_ptr<int>return unique_ptr<int> (new int(p));
}
//还可以返回一个局部对象的拷贝
unique_ptr<int> clone(int p){unique_ptr<int> ret(new int(p));//...return ret;
}
weak_ptr:是一种不控制所指向对象生存期的智能指针,它指向一个shared_ptr管理的对象。
创建一个weak_ptr时,要用一个shared_ptr来初始化它
auto p = make_shared<int>(42);
weak_ptr<int> wp(p);//wp弱共享p;p的引用计数未改变if(shared_ptr<int> np = wp.lock()){//如果np不为空则条件成立//在if中,np与p共享对象
}
核查指针类:
//对于访问一个不存在元素的尝试,StrBlobPtr抛出一个尝试
class StrBlobPtr{
public:StrBlobPtr(): curr(0){ }StrBlobPtr(StrBlob &a, size_t sz = 0):wptr(a.data), curr(sz){ }std::string& deref() const;StrBlobPtr& incr();//前缀递增
private://若检查成功,check返回一个指向vector的shared_ptrstd::shared_ptr<std::vector<std::string>>check(std::size_t, const std::string&) const;//保存一个weak_ptr,意味着底层vector可能被销毁std::weak_ptr<std::vector<std::string>> wptr;std::size_t curr;//在数组中的当前位置
}//StrBlobPtr的check成员与StrBlob中的同名成员不同,它还要检查指针指向的vector是否还存在
std::shared_ptr<std::vector<std::string>>
StrBlobPtr::check(std::size_t i, const std::string &msg) const
{auto ret = wptr.lock();//vector还存在吗?if(!ret)throw std::runtime_error("unbound StrBlobPtr");if(i>=ret->size())throw std::out_of_range(msg);return ret;//否则,返回指向vector的shared_ptr
}
指针操作:
//deref成员调用check,检查使用vector是否安全以及curr是否在合法范围内
std::string& StrBlobPtr::deref() const
{auto p = check(curr, "dereference past end");return (*p)[curr]; //(*p)是对象所指向的vector
}//incr成员也调用check
//前缀地递增:返回递增后的对象的引用
StrBlobPtr& StrBlobPtr::incr()
{//如果curr已经指向容器的尾后位置,就不能递增它check(curr, "increment past end of StrBlobPtr");++cur;//推进当前位置return *this;
}//对于StrBlob中的友元声明来说,此前置声明是必要的
class StrBlobPtr;
class StrBlob{friend class StrBlobPtr;//返回指向首元素和尾后元素的StrBlobPtrStrBlobPtr begin() { return StrBlobPtr(*this); }StrBlobPtr end(){auto ret = StrBlobPtr(*this, data->size());return ret;}
}
动态数组
new和数组:让new分配一个动态数组,需要在类型名之后跟一对方括号,在其中指明要分配的对象的数目。
//调用get_size确定分配多少个int
int *pia = new int[get_size()];//pia指向第一个inttypedef int arrT[42];//arrT表示42个int的数组类型
int *p = new arrT;//分配一个42个int的数组;p指向第一个int
初始化动态分配对象的数组:默认情况下,new分配的对象,都是默认初始化的。
int *pia = new int[10];//10个未初始化的int
int *pia2 = new int[10];//10个值初始化为0的int
string *psa = new string[10];//10个空string
string *psa2 = new string[10]();//10个空string//10个int分别用列表中对应的初始化器初始化
int *pia3 = new int[10]{0,1,2,3,4,5,6,7,8,9};
//10个string,前4个用给定的初始化器初始化,剩余的进行值初始化
string *psa3 = new string[10]{"a", "an", "the", string(3,'x')};
动态分配一个空数组是合法的:
size_t n = get_size();//get_size返回需要的元素的数目
int* p = new int[n]; //分配数组保存元素
for(int* q = p; q != p+n; ++q)/*处理数组*/;char arr[0];//错误:不能定义长度为0的数组
char *cp = new char[0];//正确:但cp不能解引用
释放动态数组:
delete p;//p必须指向一个动态分配的对象或为空
delete [] pa;//pa必须指向一个动态分配的数组或为空typedef int arrT[42];//arrT是42个int的数组的类型别名
int *p = new arrT;//分配一个42个int的数组;p指向第一个元素
delete []p;//方括号是必须的,因为我们当初分配的是一个数组
智能指针与动态数组:标准库提供了一个可以管理new分配的数组的unique_ptr版本。为了用一个unique_ptr管理动态数组,我们必须在对象类型后面跟一对空方括号。
//up指向一个包含10个未初始化int的数组
unique_ptr<int[]> up(new int[10]);
up.release();//自动用delete[]销毁其指针for(size_t i = 0; i!=10; ++i)up[i] = i;//为每个元素赋予一个新值//为了使用shared_ptr,必须提供一个删除器
shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
sp.reset();//使用我们提供的lambda释放数组,它使用delete[]//shared_ptr未定义下标运算符,并且不支持指针的算术运算
for(size_t i=0; i!=10; ++i)*(sp.get() + i) = i;//使用get获取一个内置指针
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GUiCOZIp-1677828130213)(C:\Users\21147\AppData\Roaming\Typora\typora-user-images\1675233306285.png)]
allocator类:定义在头文件memory中,将内存分配和对象构造分离开来。当一个allocator对象分配内存时,它会根据给定的对象类型来确定恰当的内存大小和对齐位置:
allocator<string> alloc;//可以分配string的allocator对象
auto const p = alloc.allocate(n);//分配n个未初始化的string
allocator分配未构造的内存:
auto q = p;//q指向最后构造的元素之后的位置
alloc.construct(q++);//*q为空字符串
alloc.construct(q++, 10, 'c');//*q为cccccccccc
alloc.construct(q++, "hi"); //*q为hicout<<*p<<endl;//正确:使用string的输出运算符
cout<<*q<<endl;//灾难:q指向未构造的内存!
拷贝和填充未初始化内存的算法:
//分配比vi中元素所占用空间大一倍的动态内存
auto p = alloc.allocate(vi.size()*2);
//通过拷贝vi中的元素来构造从p开始的元素
auto q = uninitialized_copy(vi.begin(), vi.end(), p);
//将剩余元素初始化为42
uninitialized_fill_n(q,vi.size(),42);
概念总结
为了更安全地使用动态对象,标准库定义了两个智能指针俩管理动态分配的对象。当一个对象应该被释放时,指向它的智能指针可以确保自动地释放它。
静态内存:保存局部static对象、类static数据成员以及定义在任何函数之外的变量。
栈内存:保存定义在函数内的非static对象。分配在静态或栈内存的对象由编译器自动创建和销毁。
对于栈对象,仅在其定义的程序运行时才存在;static对象在使用之前分配,在程序结束时销毁。
shared_ptr为什么没有release成员?
相关文章:
《C++ Primer》 第十二章 动态内存
《C Primer》 第十二章 动态内存 动态内存与智能指针 shared_ptr允许多个指针指向同一个对象;unique_ptr则“独占”所指向的对象,weak_ptr指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。 shared_ptr类:默认初始化的智能…...
多个关键字用or、and、包含、不包含动态拼接为正则表达式和SQL查询条件
目录前言校验思路1、存储方式2、实现图一实现图二实现结果最后前言 不知道大家有没有做过这种需求:在某字符串中,根据多个关键字去判断这串字符串是否满足条件。如下图: 亦或是 如果说要根据图二的关键字去数据库中查询符合条件的数据&a…...
初始Linux操作系统
个人简介:云计算网络运维专业人员,了解运维知识,掌握TCP/IP协议,每天分享网络运维知识与技能。座右铭:海不辞水,故能成其大;山不辞石,故能成其高。个人主页:小李会科技的…...
【算法数据结构体系篇class12、13】:二叉树
一、判断二叉树是否是完全二叉树/*** 判断二叉树是否是完全二叉树** //判断层序遍历过程如果节点有右子树 没有左子树 那么就不是完全二叉树* //判断层序遍历过程如果遇到第一个节点是没有左或右子树的,也就是只有一个子节点或者没有,那么再往后层序遍历…...
数字IC手撕代码--联发科(总线访问仲裁)
题目描述当A、B两组的信号请求访问某个模块时,为了保证正确的访问,需要对这些信号进行仲裁。请用Verilog实现一个仲裁器,对两组请求信号进行仲后,要求:协议如图所示,请求方发送req(request&…...
白盒测试复习重点
白盒测试白盒测试之逻辑覆盖法逻辑覆盖用例设计方法1.语句覆盖2.判定覆盖(分支覆盖)3.条件覆盖4.判定条件覆盖5.条件组合覆盖6.路径覆盖白盒测试之基本路径测试法基本路径测试方法的步骤1.根据程序流程图画控制流图2.计算圈复杂度3.导出测试用例4.准备测试用例5.例题白盒测试总…...
学习C++这几个网站足矣
文章目录cppreferencecplusplusquick-bench[C 之父的网站](https://www.stroustrup.com/bs_faq.html)C提案[Cpp Core Guidelines](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)[C Super-FAQ](https://isocpp.org/faq)[learn c](https://www.learncpp.com/)[A…...
第十四届蓝桥杯模拟赛(第三期)——C语言版
1.找最小数 问题描述: 请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。 请将这个数的十进制形式作为答案提交。 #include <stdio.h> int main(…...
Flutter Button 实例
大家好,我是 17。 在上篇文章 使用 Flutter Button 介绍了如何修改 button 的样式,本文来具体实践一下。 本文列举一些常用的 button 效果,以便在用到的时候方便使用。因为 ElevatedButton 最常用,所以大多以 ElevatedButton 举…...
好玩的docker项目,盒子刷的海思nas,挂载外接硬盘。qb种子
玩法思路(5条消息) 群晖qb下载,tr辅种_屿兮的博客-CSDN博客_群晖辅种qbittorrent简介及设置_哔哩哔哩_bilibiliqb下载器下载Transmission最好用的BT(PT)下载神器/超简单上手教你在NAS轻松部署/告别简陋三步让你升级全中文最新Web界面(BT下载/PT下载/NAS/…...
RabbitMQ的使用
1.初识MQ1.1.同步和异步通讯微服务间通讯有同步和异步两种方式:同步通讯:就像打电话,需要实时响应。异步通讯:就像发邮件,不需要马上回复。两种方式各有优劣,打电话可以立即得到响应,但是你却不…...
Selenium如何隐藏浏览器页面?
Selenium隐藏浏览器页面 背景 在工作,学习中,我们常常会使用selenium来获取网页上的数据,编完完整程序之后,实现真正意义上的自动化获取,此时我们会发现在运行中往往会弹出浏览器页面,在调试过程中&…...
基于Ant DesignPro Vue实现通过SpringBoot后台加载自定义菜单- 前后端分离
基于Ant DesignPro Vue实现通过SpringBoot后台加载自定义菜单- 前后端分离 本文想基于Ant DesignPro Vue构建的前端SpringBoot实现的后端接口服务,实现前后端分离开发和独立运行,业务场景是登录认证,认证成功后返回该用户相应权限范围内可见的…...
Acwing---843. n-皇后问题
n-皇后问题1.题目2.基本思想3.代码实现1.题目 n−皇后问题是指将 n 个皇后放在 nn 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。 现在给定整数 n,请你输出所有的满足条件的棋子摆法。 …...
彻底搞清楚内存泄漏的原因,如何避免内存泄漏,如何定位内存泄漏
作为C/C开发人员,内存泄漏是最容易遇到的问题之一,这是由C/C语言的特性引起的。C/C语言与其他语言不同,需要开发者去申请和释放内存,即需要开发者去管理内存,如果内存使用不当,就容易造成段错误(segment fa…...
自动驾驶目标检测项目实战——基于深度学习框架yolov的交通标志检测
自动驾驶目标检测项目实战——基于深度学习框架yolov的交通标志检测 目前目标检测算法有很多,流行的就有faster-rnn和yolov,本文使用了几年前的yolov3框架进行训练,效果还是很好,当然也可以使用更高版本的Yolov进行实战。本代码使…...
flink兼容性验证
flink介绍:https://blog.csdn.net/weixin_43563705/article/details/107604693 一、安装启动 安装flink及其依赖 yum install java-1.8.0-openjdk curl tar mkdir -p /usr/local/flink wget https://mirrors.aliyun.com/apache/flink/flink-1.16.1/flink-1.16.1-bi…...
智慧工厂数字孪生可视化监测系统有效提升厂区安全管控效力
我国制造业正处于产业升级的关键时期,基于数据进行生产策略制定与管理是大势所趋,而数据可视化以更直观的方式成为数据分析传递信息的重要工具。 深圳华锐视点通过三维可视化手段对工厂各类设备进行三维建模,真实复现设备设施外观、结构、运转…...
c++中基本类型详细解释外加基本运算规则
👀👀#c中包括算数类型和空类型。 类型含义wchat_t宽字符bool布尔类型char字符chat16_tunicode字符chat_32unicode字符short短整型int整形long长整型longlong长整型float单精度浮点型double双精度浮点型longdouble扩展精度浮点型 👀…...
扬帆优配“机器人+”方案加码产业发展,这些股有望高增长
“机器人”发明新需求,2022年中国机器人市场规模约为174亿美元。 美国时刻3月1日,特斯拉在得克萨斯州超级工厂举办投资者日活动,展示了人形机器人Optimus的视频,更夸大的是,视频中的机器人好像在制作另一个机器人&…...
推送投票制作微信推送里投票制作教程在线投票活动制作
近些年来,第三方的微信投票制作平台如雨后春笋般络绎不绝。随着手机的互联网的发展及微信开放平台各项基于手机能力的开放,更多人选择微信投票小程序平台,因为它有非常大的优势。1.它比起微信公众号自带的投票系统、传统的H5投票系统有可以图…...
【架构师】跟我一起学架构——微服务分层监控
博客昵称:架构师Cool 最喜欢的座右铭:一以贯之的努力,不得懈怠的人生。 作者简介:一名Coder,软件设计师/鸿蒙高级工程师认证,在备战高级架构师/系统分析师,欢迎关注小弟! 博主小留言…...
Linux:https静态网站搭建案例
目录介绍httpshttps通信过程例介绍https 整个实验是在http实验基础上进行的 因为http协议在传输的时候采用的是明文传输,有安全隐患,所以出现了https(安全套接字层超文本传输协议) HTTPS并不是一个新协议, 而是HTTP…...
前端css整理
如何水平垂直居中一个盒子? 1.已知高度:子盒子设置 display: inline-block; 父盒子设置 line-height 等于高度实现垂直居中;使用 text-align:center实现水平居中 2.父盒子 display:flex; align-items:center;justify-content:center; 3.定位&…...
混凝土搅拌站远程监控解决方案
一、项目背景 随着大规模的基础设施建设,对混凝土搅拌设备的需求量日益增加,对其技术指标的要求也日益提高,其技术性能将直接关系到工程的质量和使用寿命。而混凝土生产的质量是在生产过程中形成的,而非最终强度的检测。混凝土生…...
Spark SQL 学习总结
文章目录(一)Spark SQL(二)SParkSession(三)DataFrame常见算子操作(四)DataFrame的sql操作(五)RDD转换为DataFrame(1)反射方式&#x…...
深度学习 - 37.TF x Keras Deep Cross Network DCN 实现
目录 一.引言 二.模型简介 1.Embedding and stacking layer 2.Cross Network 2.1 模型架构分析 2.2 计算逻辑...
Ubuntu中使用Synaptic进行包管理
Synaptic概况 Synaptic 是一个轻量级的 apt 软件包管理器系统的 GUI 前端,所有你可以在终端中使用 apt-get 命令来做的事,都可以通过 Synaptic 来实现。优势 图形化安装界面,同时可以安装配置相关依赖,避免由于依赖问题导致的各类…...
python之selenium库安装及用法(定位法、获取文本、文本框输入、鼠标点击、滑动滚动条)
一、selenium库安装 pip install selenium二、浏览器驱动安装 谷歌浏览器驱动下载地址:https://chromedriver.storage.googleapis.com/index.html 根据你电脑的谷歌浏览器版本,下载相应的就行。我下载的是110.0.5481.XX中的chromedriver_win32.zip 下载…...
FPGA纯verilog实现图像视频旋转 串口指令控制旋转角度 提供工程源码和技术支持
目录1、前言2、理论基础3、设计思路和框架图像输入和采集图像旋转处理图像缓存图像输出4、vivado工程详解5、上板调试验证6、福利:工程代码的获取1、前言 图像旋转是一种常用的图像处理技术,其基本原理就是指图像以某一点为中心旋转一定的角度ÿ…...
网站建设三网/什么推广软件效果好
------------------ --------1 执行不带参数的hql文件---------------------------- hive -f 文件名.后缀 实例:hive -f chensq_test1.hql------------------ -----2 执行带1个普通参数的hql文件---------------------------- ----- 直接在hive中执行----select co…...
北京市顺义住房建设委官方网站/国外推广渠道平台
支付汇款——变革的前夜 比特币于2009年诞生之始,也许只是微露曙光,理想主义者便敏锐地嗅觉到了“世外桃源”的味道。于是乎, 比特币以摧枯拉朽之势,被挖掘、被追逐、被高高捧起,成就了一批新富的狂欢,接踵…...
wordpress4.7.1漏洞/推广普通话图片
基于:【狂神说Java】SpringMVC最新教程IDEA版通俗易懂 目录1 web.xml配置2 springmvc-servlet配置3 具体Controller类4 jsp5 总结1 web.xml配置 <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/x…...
网站建设需要多钱/360推广和百度推广哪个好
什么是Zookeeper Zookeeper是一个高性能,分布式的,开源分布式应用协调服务。它提供了简单原始的功能,分布式应用可以基于它实现更高级 的服务,比如同步,配置管理,集群管理,名空间。它被设计为易…...
杭州做网站公司/优化疫情二十条措施
在bootstrap中,我们可以使用不带任何class的跟来创建一个有序列表,但是如果加上list-group类,样式有了,但列表前面的数字却没了。Bootstrap给list-group-item应用了display:block; 所以显示不了序号,因此我们只要修改一…...
中国建设银行行号查询网站/服务营销7p理论
当我们需要遍历一个数组时,第一个想到的就是for,然后用length去判断条件,之后,但着似乎有些过于老套了。本文主要收集各种遍历方法,主要针对数组,也会有关于对象、字符串的,看完它,你…...