C++之智能指针
前言
普通指针的不足
new和new门的内存需要用delete和delete[释放。
程序员的主观失误,忘了或漏了释放
程序员也不确定何时释放(例如多个线程共享同一个对象,没办法确定什么时候释放)
普通指针的释放
类内的指针,在析构函数中释放
C++内置数据类型,如何释放?
new出来的类,本身如何释放?
智能指针设计思路
智能指针是类模板,在栈上创建智能指针对象
把普通指针交给智能指针对象
智能指针对象过期时,调用析构函数释放普通指针的内存
什么是智能指针
智能指针是RALL机制对普通指针进行的一层封装。这样使得智能指针的行为动作像一个指针,本质上却是一个对象,这样可以方便管理一个对象的生命周期。
智能指针详解
unique_ptr
定义:unique_ptr独享它指向的对象,也就是说,同时只有一个unique_ptr指向同一个对象,当这个unique_ptr被销毁时,指向的对象也随即被销毁。
头文件:#include<memory>
template <typename T, typename D = default_delete<T>>
class unique_ptr
{
public:explicit unique_ptr(pointer p) noexcept; // 不可用于转换函数。~unique_ptr() noexcept; T& operator*() const; // 重载*操作符。T* operator->() const noexcept; // 重载->操作符。unique_ptr(const unique_ptr &) = delete; // 禁用拷贝构造函数。unique_ptr& operator=(const unique_ptr &) = delete; // 禁用赋值函数。unique_ptr(unique_ptr &&) noexcept; // 右值引用。unique_ptr& operator=(unique_ptr &&) noexcept; // 右值引用。// ...
private:pointer ptr; // 内置的指针。
};
下面进行测试
#include<memory>
#include<iostream>
#include<vector>
using namespace std;
class AA
{
public:string m_name;AA() { cout << m_name << "调用构造函数AA()。" << endl;}AA(const string& name) : m_name(name) {cout << "调用构造函数AA(" << m_name << ")。" << endl;}~AA() { cout << "调用了析构函数~AA(" << m_name << ")。" << endl;}
};
测试1
void test1()
{AA* p = new AA("张三");//delete p; //这里结社我们忘记delete
}
运行结果:
调用构造函数AA(张三)。
我们发现出现了内存泄漏问题,这里我们是故意忘记释放,但是真正到了开发时,都有可能会忘记释放,那怎么办呢?我们可以用智能指针unique_ptr
测试2
void test2()
{AA* p = new AA("张三");unique_ptr<AA> p1(p);
}
运行结果
调用构造函数AA(张三)。
张三调用了析构函数~AA(张三)。
我们惊奇的发现我们没有调用delete,但是也调用了析构函数,因为智能指针是一个类,它有析构函数,在析构函数中有delete语句。
并且类重载了->和*,可以像使用普通指针一样使用智能指针
测试3
void test3()
{AA* p = new AA("张三");unique_ptr<AA> p1(p);cout << (*p1).m_name << endl;cout << p1->m_name << endl;cout << p->m_name << endl;cout << (*p).m_name << endl;
}
运行结果
调用构造函数AA(张三)。
张三
张三
张三
张三
张三调用了析构函数~AA(张三)。
基本用法
初始化
//方法1
unique_ptr<AA> p0(new AA("西施")); // 分配内存并初始化
//方法2
unique_ptr<AA> p0 = make_unique<AA>("西施"); // C++14标准。
unique_ptr<int> pp1=make_unique<int>(); // 数据类型为int。
unique_ptr<AA> pp2 = make_unique<AA>(); // 数据类型为AA,默认构造函数。
unique_ptr<AA> pp3 = make_unique<AA>("西施"); // 数据类型为AA,一个参数的构造函数。
unique_ptr<AA> pp4 = make_unique<AA>("西施",8); // 数据类型为AA,两个参数的构造函数。
//方法3
AA* p = new AA("西施");
unique_ptr<AA> p0(p); // 用已存在的地址初始化。
注意:
重载了->和*,可以像使用普通指针一样使用unique_ptr
不支持普通的拷贝和赋值
explicit unique_ptr(pointer p) noexcept; // 因为有explicit,所以不可用于转换函数。
unique_ptr(const unique_ptr &) = delete; // 禁用拷贝构造函数
unique_ptr& operator=(const unique_ptr &) = delete; // 禁用赋值函数。
例如以下测试错误的
void test4()
{AA* p = new AA("张三");unique_ptr<AA> p1 = p; //错误,不能将普通指针直接复制给智能指针unique_ptr<AA>p2 = new AA("李四"); //错误,不能将普通指针直接复制给智能指针unique_ptr<AA> p3 = pu1; // 错误,不能用其它unique_ptr拷贝构造unique_ptr<AA> p4;p4=p1; //错误,不能用=对unique_ptr进行赋值
}
为什么要禁用赋值函数呢?
这个与智能指针实现初衷有关,unique_ptr实现的是一个指针独享一份资源,如果可以复制的话,那个就会出现多个unique_ptr指针指向同一块资源,就会出现非法操作野指针。
不要用同一个裸指针初始化多个unique_ptr对象(也是出现非法操作野指针问题);
不要用unique_ptr管理不是new分配的内存;
get()方法返回裸指针;
用于函数的参数只能传引用;
不支持指针运算(+、-、++、--)。
技巧
1. 将一个unique_ptr赋给另一个时,如果原unique_ptr是一个临时右值,编译器允许这样做;如果源unique_ptr将存在一段时间,编译器禁止这样做。一般用于函数的返回值;
2. 用nullptr给unique_ptr赋值将释放对象,空的unique_ptr==nullptr;
3. release()释放对原始指针的控制权,将unique_ptr置为空,返回裸指针。(可用于把unique_ptr传递给子函数,子函数将负责释放对象);
4. std::move()可以转移对原始指针的控制权。(可用于把unique_ptr传递给子函数,子函数形参也是unique_ptr);
5. reset()释放对象;
6. swap()交换两个unique_ptr的控制权;
7. unique_ptr也可象普通指针那样,当指向一个类继承体系的基类对象时,也具有多态性质,如同使用裸指针管理基类对象和派生类对象那样;
8. unique_ptr不是绝对安全,如果程序中调用exit()退出,全局的unique_ptr可以自动释放,但局部的unique_ptr无法释放;
9. unique_ptr提供了支持数组的具体化版本。数组版本的unique_ptr,重载了操作符[],操作符[]返回的是引用,可以作为左值使用。
这里只演示第1、4、5、8、9;
示例 1:
unique_ptr<AA> func()
{unique_ptr<AA> pp(new AA("小谢"));return pp;
}
void test4()
{unique_ptr<AA> p1(new AA("张三"));unique_ptr<AA> p2;//p2 = p1;p2 = unique_ptr<AA>(new AA("李四"));cout << "调用func之前" << endl;p2 = func();cout << "调用func之后" << endl;
}
示例 4
void func(unique_ptr<AA> a)
{cout << a->m_name << endl;
}
void test5()
{unique_ptr<AA>pu(new AA("张三"));cout << "开始调用函数" << endl;func(move(pu));cout << "调用函数结束" << endl;
}
这里函数调用时使用了move函数,将pu的管理权交给形参
示例 5
void reset(T * _ptr= (T *) nullptr);
pp.reset(); // 释放pp对象指向的资源对象。
pp.reset(nullptr); // 释放pp对象指向的资源对象
pp.reset(new AA("bbb")); // 释放pp指向的资源对象,同时指向新的对象。
示例 8
unique_ptr<AA> p(new AA("全局"));
int main()
{unique_ptr<AA> p1(new AA("局部"));exit(0);
}
结果
调用构造函数AA(全局)。
调用构造函数AA(局部)。
全局调用了析构函数~AA(全局)。
示例 9
unique_ptr<int[]> parr1(new int[3]); // 不指定初始值。
unique_ptr<int[]> parr1(new int[3]{ 33,22,11 }); // 指定初始值。
cout << "parr1[0]=" << parr1[0] << endl;
cout << "parr1[1]=" << parr1[1] << endl;
cout << "parr1[2]=" << parr1[2] << endl;
shared_ptr
定义:
shared_ptr共享它指向的对象,多个shared_ptr可以指向(关联)相同的对象,在内部采用计数机制来实现。
当新的shared_ptr与对象关联时,引用计数增加1。
当shared_ptr超出作用域时,引用计数减1。当引用计数变为0时,则表示没有任何shared_ptr与对象关联,则释放该对象。
基本用法
初始化
shared_ptr的构造函数也是explicit,但是,没有删除拷贝构造函数和赋值函数。
//方法一:
shared_ptr<AA> p0(new AA("西施")); // 分配内存并初始化。
//方法二:
shared_ptr<AA> p0 = make_shared<AA>("西施"); // C++11标准,效率更高。
shared_ptr<int> pp1=make_shared<int>(); // 数据类型为int。
shared_ptr<AA> pp2 = make_shared<AA>(); // 数据类型为AA,默认构造函数。
shared_ptr<AA> pp3 = make_shared<AA>("西施"); // 数据类型为AA,一个参数的构造函数。
shared_ptr<AA> pp4 = make_shared<AA>("西施",8); // 数据类型为AA,两个参数的构造函数。
//方法三:
AA* p = new AA("西施");
shared_ptr<AA> p0(p); // 用已存在的地址初始化。
//方法四:
shared_ptr<AA> p0(new AA("西施"));
shared_ptr<AA> p1(p0); // 用已存在的shared_ptr初始化,计数加1。
shared_ptr<AA> p1=p0; // 用已存在的shared_ptr初始化,计数加1
注意:
智能指针重载了*和->操作符,可以像使用指针一样使用shared_ptr;
use_count()方法返回引用计数器的值;
unique()方法,如果use_count()为1,返回true,否则返回false
shared_ptr支持赋值,左值的shared_ptr的计数器将减1,右值shared_ptr的计算器将加1(当某个资源没有指向时就会被释放);
get()方法返回裸指针;
不要用同一个裸指针初始化多个shared_ptr;
不要用shared_ptr管理不是new分配的内存;
用于函数的参数只能传引用;
不支持指针运算(+、-、++、--)。
技巧
1. 用nullptr给shared_ptr赋值将把计数减1,如果计数为0,将释放对象,空shared_ptr==nullptr;
2. std::move()可以转移对原始指针的控制权。还可以将unique_ptr转移成shared_ptr;
3. reset()改变与资源的关联关系;
pp.reset(); // 解除与资源的关系,资源的引用计数减1。
pp. reset(new AA("bbb")); // 解除与资源的关系,资源的引用计数减1。关联新资源。
4. swap()交换两个shared_ptr的控制权;
void swap(shared_ptr<T> &_Right);
5. shared_ptr也可象普通指针那样,当指向一个类继承体系的基类对象时,也具有多态性质,如同使用裸指针管理基类对象和派生类对象那样;
6. shared_ptr不是绝对安全,如果程序中调用exit()退出,全局的shared_ptr可以自动释放,但局部的shared_ptr无法释放;
7. shared_ptr提供了支持数组的具体化版本;
数组版本的shared_ptr,重载了操作符[],操作符[]返回的是引用,可以作为左值使用;
8. shared_ptr的线程安全性:
shared_ptr的引用计数本身是线程安全(引用计数是原子操作)。
多个线程同时读同一个shared_ptr对象是线程安全的。
如果是多个线程对同一个shared_ptr对象进行读和写,则需要加锁。
多线程读写shared_ptr所指向的同一个对象,不管是相同的shared_ptr对象,还是不同的shared_ptr对象,也需要加锁保护。
9. 如果unique_ptr能解决问题,就不要用shared_ptr。unique_ptr的效率更高,占用的资源更少。
weak_ptr
定义
weak_ptr 是为了配合shared_ptr而引入的,它指向一个由shared_ptr管理的资源但不影响资源的生命周期。也就是说,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。
不论是否有weak_ptr指向,如果最后一个指向资源的shared_ptr被销毁,资源就会被释放。
weak_ptr更像是shared_ptr的助手而不是智能指针
这里举个例子
#include <iostream>
#include <memory>
using namespace std;
class BB;
class AA
{
public:string m_name;AA() { cout << m_name << "调用构造函数AA()。\n"; }AA(const string& name) : m_name(name) { cout << "调用构造函数AA(" << m_name << ")。\n"; }~AA() { cout << "调用了析构函数~AA(" << m_name << ")。\n"; }shared_ptr<BB> m_p;
};
class BB
{
public:string m_name;BB() { cout << m_name << "调用构造函数BB()。\n"; }BB(const string& name) : m_name(name) { cout << "调用构造函数BB(" << m_name << ")。\n"; }~BB() { cout << "调用了析构函数~BB(" << m_name << ")。\n"; }shared_ptr<AA> m_p;
};
int main()
{shared_ptr<AA> pa = make_shared<AA>("西施a");shared_ptr<BB> pb = make_shared<BB>("西施b");pa->m_p = pb;pb->m_p = pa;
}
程序结果:
显然AA和BB都没有析构,这是为什么呢??
AA中有类BB的指针指向pb,BB中有类AA的指针指向pa,所以pa和pb不知道谁先“死”,所以程序没办法判断谁先析构,最后干脆不析构了。
那怎么解决这个问题呢(智能指针的循环引用问题)?这里引出了weak_ptr指针,代码修改如下
基本用法
weak_ptr没有重载 ->和 *操作符,不能直接访问资源。
有以下成员函数:
1)operator=(); // 把shared_ptr或weak_ptr赋值给weak_ptr。
2)expired(); // 判断它指资源是否已过期(已经被销毁)。
3)lock(); // 返回shared_ptr,如果资源已过期,返回空的shared_ptr。
4)reset(); // 将当前weak_ptr指针置为空。
5)swap(); // 交换。
weak_ptr不控制对象的生命周期,但是,它知道对象是否还活着。
用lock()函数把它可以提升为shared_ptr,如果对象还活着,返回有效的shared_ptr,如果对象已经死了,提升会失败,返回一个空的shared_ptr。
提升的行为(lock())是线程安全的。
进行测试
int main()
{shared_ptr<AA> pa = make_shared<AA>("西施a");{shared_ptr<BB> pb = make_shared<BB>("西施b");pa->m_p = pb;pb->m_p = pa;shared_ptr<BB> pp = pa->m_p.lock(); // 把weak_ptr提升为shared_ptr。if (pp == nullptr)cout << "语句块内部:pa->m_p已过期。\n";elsecout << "语句块内部:pp->m_name=" << pp->m_name << endl;}shared_ptr<BB> pp = pa->m_p.lock(); // 把weak_ptr提升为shared_ptr。if (pp == nullptr)cout << "语句块外部:pa->m_p已过期。\n";elsecout << "语句块外部:pp->m_name=" << pp->m_name << endl;
}
运行结果
删除器
#include <iostream>
#include <memory>
using namespace std;class AA
{
public:string m_name;AA() { cout << m_name << "调用构造函数AA()。" << endl; }AA(const string& name) : m_name(name) { cout << "调用构造函数AA(" << m_name << ")。" << endl; }~AA() { cout << "调用了析构函数~AA(" << m_name << ")。" << endl; }
};void deletefunc(AA* a) { // 删除器,普通函数。cout << "自定义删除器(全局函数)。" << endl;delete a;
}struct deleteclass // 删除器,仿函数。
{void operator()(AA* a) {cout << "自定义删除器(仿函数)。" << endl;delete a;}
};auto deleterlamb = [](AA* a) { // 删除器,Lambda表达式。cout << "自定义删除器(Lambda)。" << endl;delete a;
};int main()
{shared_ptr<AA> pa1(new AA("张三")); //不填,默认使用缺省//shared_ptr<AA> pa1(new AA("张三"), deletefunc);//shared_ptr<AA> pa2(new AA("李四"), deleteclass());//shared_ptr<AA> pa3(new AA("王五"), deleterlamb);//unique_ptr<AA,decltype(deletefunc)*> pu1(new AA("张三"), deletefunc);//unique_ptr<AA, void (*)(AA*)> pu0(new AA("李四"), deletefunc);//unique_ptr<AA, deleteclass> pu2(new AA("王五"), deleteclass());//unique_ptr<AA, decltype(deleterlamb)> pu3(new AA("小谢"), deleterlamb);return 0;
}
相关文章:
C++之智能指针
前言普通指针的不足new和new门的内存需要用delete和delete[释放。程序员的主观失误,忘了或漏了释放程序员也不确定何时释放(例如多个线程共享同一个对象,没办法确定什么时候释放)普通指针的释放类内的指针,在析构函数中…...
Redis实战-session共享之修改登录拦截器
在上一篇中Redis实战之session共享,我们知道了通过Redis实现session共享了,那么token怎么续命呢?怎么刷新用户呢?本来咱们就通过拦截器来实现这两个功能。 登录拦截器优化: 先来看看现在拦截器情况: 拦截…...
数据可视化,流程化处理pycharts-
本文直接进入可视化,输入讲解输入列表生成图片,关于pandas操作看这篇pandas matplotlib 导包后使用 import matplotlib.pyplot as plt饼图 使用 plt.figure 函数设置图片的大小为 15x15 使用 plt.pie 函数绘制饼图,并设置相关的参数&…...
1626_MIT 6.828 lab1课程大纲学习过程整理
全部学习汇总: GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 现在lab1的内容全都学习完了,该做的练习也都做了。接下来,整理一下自己看这一部分课程讲义的一些笔记。 整理之前,先把自己完成…...
12月无情被辞:想给还不会自动化测试的技术人提个醒
公司前段时间缺人,也面了不少测试,结果竟没有一个合适的。一开始瞄准的就是中级的水准,也没指望来大牛,提供的薪资在10-20k,面试的人很多,但是平均水平很让人失望。基本能用一句话概括就是:3年测…...
开发必备技术--docker(使用篇)
文章目录前言Docker的基本概念概念数据卷虚拟网络镜像操作镜像名称镜像命令容器操作基本操作容器创建数据卷操作创建和查看数据卷其他指令实战前言 续接上一篇博文: 开发必备技术–docker(一) 这也是开学了,假期的最后一篇博文&a…...
2023备战金三银四,Python自动化软件测试面试宝典合集(三)
马上就又到了程序员们躁动不安,蠢蠢欲动的季节~这不,金三银四已然到了家门口,元宵节一过后台就有不少人问我:现在外边大厂面试都问啥想去大厂又怕面试挂面试应该怎么准备测试开发前景如何面试,一个程序员成长之路永恒绕…...
TortoiseGit 使用教程
一、下载工具 这里给大家准备了所有安装包自取 链接:https://pan.baidu.com/s/1xrxxgyNXNQEGD_RjwKnPMg 提取码:qwer 也可在官网自行下载最新版 1.下载git,直接去官网下载Git - Downloads,根据自己的系统合理下载,…...
Linux项目自动化构建工具make/Makefile
本文已收录至《Linux知识与编程》专栏! 作者:ARMCSKGT 演示环境:CentOS 7 目录 前言 正文 makefile文件与语法规则 make指令与执行逻辑 makefile任务刷新策略 .PHONY修饰为伪目标 最后 前言 会不会写makefile,从一个侧面…...
M100嵌入式自动吞吐式读写器|电动读卡机如何通过C#程序读取社保卡号
M100嵌入式自动吞吐式读写器|电动读卡机是一款双保护门功能读卡器,第一层防尘防异物机械门,第二层电动门。 M100嵌入式自动吞吐式读写器|电动读卡机采用耐高温、耐磨擦、高强度、抗老化的复合型塑胶为主体,在走卡通道两侧镶有不锈钢金属&…...
STM32----搭建Arduino开发环境
搭建Arduino开发环境前言一、Arduino软件1.软件下载2.软件安装3.软件操作二、Cortex官方内核三、烧录下载四、其他第三方内核1.Libmaple内核2.Steve改进的LibMaple 内核3.STMicroelectronics(ST)公司编写的内核总结前言 本章介绍搭建STM32搭建Arduino开发环境,包括…...
华为OD机试 - 事件推送(Python),真机试题
事件推送 题目 同一个数轴 X 上有两个点的集合 A={A1, A2, …, Am} 和 B={B1, B2, …, Bn}, Ai 和 Bj 均为正整数,A、B 已经按照从小到大排好序,A、B 均不为空, 给定一个距离 R (正整数), 列出同时满足如下条件的所有(Ai, Bj)数对: Ai <= BjAi, Bj 之间的距离小于…...
论如何获取CSDN原力
0x00 前言 因为个人需求,所以需要增长原力值,故对原力值的增长方式进行探索和总结。 0x01 正文 参考:https://blog.csdn.net/SoftwareTeacher/article/details/114499372 1.举报了劣质内容(博客,下载的资源&#x…...
流程引擎之发展史及对比总结
流程引擎渊源市场上比较有名的开源流程引擎有 jBPM、Activiti、Camunda、Flowable 和 Compileflow。其中 jBPM、Activiti、Flowable、camunda 四个框架同宗同源,祖先都是 jbpm4,开发者只要用过其中一个框架,基本上就会用其它三个。而 Compile…...
【DSView逻辑分析抓取波形CAN步骤-硬件连接-数据解析-底层波形认识CAN-工具使用】
【DSView逻辑分析抓取波形CAN步骤-硬件连接-数据解析-底层波形认识CAN】1、概述2、实验环境3、写在前面的一个问题4、实验准备(1)硬件连接1)CAN卡连接开发板(2)逻辑分析仪连接开发板(2) CAN卡连接软件&…...
C++中的模板
1.模板C 的模板一直是这门语言的一种特殊的艺术,模板甚至可以独立作为一门新的语言来进行使用。模板的哲学在于将一切能够在编译期处理的问题丢到编译期进行处理,仅在运行时处理那些最核心的动态服务,进而大幅优化运行期的性能。因此模板也被…...
Maven_第四章 使用Maven:IDEA环境
目录第一节 创建父工程第二节 配置Maven信息第三节 创建Java模块工程第四节 创建Web模块工程1、创建模块2、修改打包方式3、Web 设定4、借助IDEA生成web.xml5、设置 Web 资源的根目录6、测试6.1 创建文件6.2 配置tomcat第五节 其他操作1、在IDEA中执行Maven命令①直接执行②手动…...
RocketMQ基础学习
前言: RocketMQ阿里开源的,一款分布式的消息中间件,它经过阿里的生产环境的高并发、高吞吐的考验,同时,还支持分布式事务等场景。RocketMQ使用Java语言进行开发,方便Java开发者学习源码。但是,R…...
I.MX6ULL内核开发4:设备号的组成与哈希表
目录 一、设备号 二、hash table 一、设备号 文件夹:/home/geralt/linux_driver/kernel/ebf_linux_kernel_6ull_depth1/include/linux/kdev.h 这里面是linux中关于设备号的具体描述 #define MINORBITS 20 #define MINORMASK ((1U << MINORBITS) - 1)#defin…...
【博学谷学习记录】大数据课程-学习第六周总结
Hadoop 3.x的版本架构和模型介绍 由于Hadoop 2.0是基于JDK 1.7开发的,而JDK 1.7在2015年4月已停止更新,这直接迫使Hadoop社区基于JDK 1.8重新发布一个新的Hadoop版本,即hadoop 3.0。Hadoop 3.0中引入了一些重要的功能和优化,包括…...
Cordova
一、简介 Cordova 是用 Web 技术( HTML,CSS 和 JS )构建移动应用的平台。我们可以认为Cordova 是一个容器,用于将的 Web 应用移植到移动端,同时支持移动端的功能(例如:定位、蓝牙、摄像头等&am…...
9.语义HTMLVScode扩展推荐
语义HTML 定义: 一个元素使用我们并不是只关心他是什么样子的,而是要去关心这个元素名称的实际意义或者代表什么 我们使用标签并不是他仅代表导航栏,只是将导航栏部分归为一个块。现实生活中,多使用之前都是使用div这个元素去构…...
一款非常不错的微信系统垃圾清理工具:微信清理大师,操作简单,清除较快。
微信清理大师 微信清理大师是一款专为微信所推出的系统垃圾清理工具。它的功能十分强大,可快捷清理微信内储存垃圾文件,操作十分简单,只需要轻轻一点,即可删除清理。 功能特点: 【一键清理】一键搞定无用垃圾&#x…...
PMP考前冲刺2.11 | 2023新征程,一举拿证
承载2023新一年的好运让我们迈向PMP终点一起冲刺!一起拿证!每日5道PMP习题助大家上岸PMP!!!题目1-2:1.以下哪三种情况是Scrum主管应该注意的障碍?(选择三个)A. 阻碍敏捷能力的技术B. 缺乏团队授…...
yalc(比 yarn/npm link 更加友好的前端依赖库 link 方案)
参考链接: 【yalc 官方文档】:https://github.com/wclr/yalc 【yalc-watch 官方文档】:https://github.com/johot/yalc-watch 链接依赖库背景 以 D-SASS 前端框架为例,当我们在修改 D-SASS 前端框架时,当想着马上就要预览到修改的内容是否生效,于是在前端框架目录下进…...
Github | 个人资料自述文件配置的不完全总结
本文简单总结配置 Github 主页上个人资料自述文件的流程和参考文件。 更新:2022 / 02 / 11 Github | 配置个人主页的信息总览方法的不完全总结创建、删除个人资料自述文件编辑个人资料自述文件参考链接创建、删除个人资料自述文件 首推自然是官方说明文档 1&#…...
2022年12月电子学会Python等级考试试卷(二级)答案解析
目录 一、单选题(共25题,共50分) 二、判断题(共10题,共20分) 三、编程题(共2题,共30分) 青少年软件编程(Python)等级考试试卷(二级) 一、单选题(共25题,共50分) 1. 运行下列程序…...
SpringCloud第二讲 Ribbon负载均衡源码分析
前言介绍: 这一讲我们将依据Eureka的负载均衡规则,Eureka的具体服务搭建以及服务注册和服务发现可以参考基于Eureka实现服务注册和服务发现_热爱Java的编程小白的博客-CSDN博客 Eureka的服务搭建之后便可以在这上面进行服务注册,如果存在两个…...
Clip-path实现按钮流动边框动画
前言 👏Clip-path实现按钮流动边框动画,速速来Get吧~ 🥇文末分享源代码。记得点赞关注收藏! 1.实现效果 2.实现步骤 添加div标签 <div>苏苏_icon</div>添加样式 div {position: relative;width: 220px;height: 6…...
不停服更新应用的方案:蓝绿发布、滚动发布、灰度发布
原文网址:不停服更新应用的方案:蓝绿发布、滚动发布、灰度发布_IT利刃出鞘的博客-CSDN博客 简介 本文介绍不停服更新应用的方案:蓝绿发布、滚动发布、灰度发布。 升级服务器的应用时,要停止掉老版本服务,将程序上传…...
东营做网站哪家好/病毒式营销案例
这里就需要了解一下Mysql提供的日志分析工具mysqldumpslow 输入帮助命令了解下mysqldumpslow的参数: mysqldumpslow --help参数说明s表示按照何种方式排序c访问次数I锁定时间r返回记录t查询时间al平均锁定时间ar平均返回记录数at平均查询时间t返回前面多少条数据g…...
微信公众号手机上传wordpress/网络快速推广渠道
微信公众号回调地址设置 ( 设置好按保存之后 微信会向该接口发送验证消息(token) 如果验证成功 配置才能生效,否则会提示错误,一会附上如何验证的代码 ) 1.在微信公众平台 > 基本配置中 > 设置地址 2.设置服务器地址 以我的回调地址为例 http:xxxxx/wxMpSendMsgCallBa…...
做哪类网站/百度ai人工智能
1、在C语言中const修饰的变量是只读的,其本质还是变量 2、const修饰的变量会在内存占用空间 3、本质上const只对编译器有用,在运行时无用 4、不能直接改变const变量的值,要用指针改变 5、const int cc 1; int *p (int *)&cc; …...
深圳网站快速优化公司/个人推广平台
1、下载软件包 整个系统的安装全过程都要求以root身份执行,如果机器没有访问外部网络的能力,则事先下载好EMOS光盘映像,并上传到服务器。 备注:如果要在CentOS 5.x上面进行配置,请下载EMOS-1.5.ISO,配置方法…...
博彩网站自己做/seo俱乐部
转自:http://www.cnblogs.com/mengdd/p/4153773.html 查看、添加、提交、删除、找回,重置修改文件 git help <command> # 显示command的help git show # 显示某次提交的内容 git show $id git co -- <file> # 抛弃工作区修改 git co . # 抛弃…...
wordpress改页面/最有效的推广方式
【Links】 https://download.qt.io/official_releases/ https://download.qt.io/official_releases/qt/ https://download.qt.io/official_releases/qtcreator/ 备注: Qt Creator是跨平台的Qt IDE,Qt Creator是Qt被Nokia收购后推出的一款新的轻量级集成…...