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

C++11

C++11

  • C++11简介
  • 一.列表初始化{ }
    • initializer_list
  • 二.一些关键字
  • 三.右值引用和移动语义(重要)
    • 完美转发
    • 移动构造和移动赋值重载
  • 四.小知识
    • 类成员变量初始化
  • 五.可变参数模板
  • 六.lambda表达式(又称匿名函数)(重要)
  • 七.多线程相关
    • thread库
    • mutex库
    • atomic库
    • condition_variable库
  • 八.包装器
    • function包装器
    • bind

C++11简介

C++11的更新一言难尽。有的更新,诸如右值引用,移动语义,unordered系列容器,lambda表达式等极有价值;有的诸如array(检查严格但没有vector好用),forward_list(虽然省空间但list更常用),cbegin接口等就很鸡肋。

一.列表初始化{ }

C++11将c语言中的用来初始化结构体和数组的{ }扩大成初始化一切类型,并且可以省略赋值符号=。

int x = { 1 };
int y{ 1 };//=可省略
//int x(1);//调用int的默认构造,注意区别开来
int a[]{ 1,2 };
string s{ "hello" };//自定义类型,本质上是构造+拷贝构造,可能优化为直接构造
int* p = new int[2] {3, 4};//支持初始化new出来的数组
vector<int>v{ 1,2,3 };//initializer_list初始化
vector<string>vs{ {"a"},{"b"} };//嵌套使用

initializer_list

0

initializer_list是C++11提出的一种类型,{ }括起来的编译器会自动识别为该类型。而vector增添了参数为initializer_list的构造函数,所以才支持{ }初始化。实际上 ,所有容器(当然不包括适配器)都增添了这种构造。另外,赋值方法也都支持{ }赋值。

auto il1 = { 1,2 };
auto il2 = { 1,2 };
cout << typeid(il1).name() << endl;
cout << typeid(il2).name() << endl;
cout << il1.begin() << endl;//begin返回的是il1的首元素地址
cout << il2.begin() << endl;
const int c = 1;
const int d = 1;
cout << &c << endl;//这3个地址接近,可见initializer_list存在常量区,不能修改

res
所以在vector中添加如下代码即可支持{ }初始化:

vector(initializer_list<T>il)
{/*typename initializer_list<T>::iterator it = il.begin();while (it != il.end()){push_back(*it++);}*/for (auto& x : il){push_back(x);}
}

评价:使用方便

二.一些关键字

  1. auto
    自动推演类型,一直都在用来简化代码,比如代替写迭代器类型,不再多言。
  2. decltype
    取出表达式的类型。
    虽然typeid可以打出类型,但你没法写在代码里。有些场景auto也无能为力,比如:两个变量相乘之后的类型要作为vector的模板参数,就只能这么写vector<decltype(x*y)>v;
  3. nullptr
    因为c语言的NULL在C++中既可以作整形的0,又可以作空指针,所以官方推荐使用nullptr当空指针使用。
  4. default
    强制生成默认函数。比如A(A&&)=default;
  5. delete
    禁掉函数,不允许生成和使用。C++98则是通过private里声明该函数来禁掉。
  6. final&override

三.右值引用和移动语义(重要)

左值:可以取地址的变量/表达式,可以出现在赋值符号=两端。
右值:不能取地址的,不能出现在=左边,即不能赋值。右值分为纯右值(内置类型的右值)和将亡值(自定义类型的右值)。包括字面常量,表达式返回值,函数传值返回值等。

int a = 0, b = 1;
int& lref1 = a;//左值引用引用左值
const int& lref2 = a + b;//左值引用引用右值
int&& rref1 = a + b;//右值引用引用右值
int&& rref2 = move(a);//右值引用引用move后的左值,但不能直接引用左值

其实,左值引用功能上足够强大了,左值右值都能引用,那为什么需要右值引用呢?
首先,右值引用底层是将被引用的右值的数据资源转移给引用者。对于纯右值,右值引用和左值引用差不多,都是同样的拷贝。但是对于深拷贝的将亡值可就意义重大了!

string(const string& s) {};//拷贝构造
string(string&& s)//移动构造,针对右值,直接交换资源即可:_str(nullptr)
{std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);
}string func()
{string str("abc");return str;
}
int main()
{string s = func();
}

见上图,s在接收时,应是2个拷贝构造,可能会被编译器优化为1个拷贝构造;在右值引用出来之后,编译器会在return str时,会在str析构之前拷贝构造一个临时对象,再用s去右值引用这个临时对象(将亡值),总计1个拷贝构造+1个移动构造,可能被优化为1个移动构造(编译器会想办法将返回的str识别成右值,类似move)。所以传值返回的深拷贝问题基本解决了。
注意,函数肯定不能传引用返回的,无论左值右值,你返回的都是局部对象的别名,出作用域就销毁了,非法访问该空间是未定义行为。比如传右值引用返回,和左值引用返回类似,不会在上一层栈帧创建临时变量来保存,所以你接收的就是个被看作右值的局部对象罢了。

总结一下:左值引用直接减少拷贝:传引用传参和传引用返回(不包括函数局部对象返回)。右值引用间接减少拷贝:针对不能传引用返回的将亡值转移资源来避免深拷贝,延长了资源的生命周期,提高效率。

和initializer_list一样,STL所有容器的构造函数和赋值函数和插入接口诸如push_back、insert等都分别添加了移动构造,移动赋值和右值引用版本

完美转发

先看代码猜结果:

void Func(int& x) { cout << "左值引用" << endl; }
void Func(const int& x) { cout << "const 左值引用" << endl; }
void Func(int&& x) { cout << "右值引用" << endl; }
void Func(const int&& x) { cout << "const 右值引用" << endl; }
//万能引用(引用折叠):函数模板参数后接&&,即可接收左值,也可接收右值
template<typename T>
void PerfectForward(T&& t)
{Func(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右值
}

在这里插入图片描述
但是结果全是左值?这是因为右值引用的引用者在接收了右值后,肯定得开空间存储这个右值,从而变得可以取地址,引用者就成了左值 (这是合理的,如果右值引用后的引用者还是右值,那string移动构造中还要怎么对s进行swap修改?)。这里同理,函数形参在接收右值后,实际上变成了左值,再传参给Func时就和左值参数相匹配。但是这是个问题啊,我们的代码为了复用,必定会有需要右值一直传递下去且要保持它的右值属性不变的场景,为此有了完美转发只要把接收右值后的引用者套上forward< T >()即可保持右值属性传递下去
下面可以认为是C++98下list的push_back实现版本:

template<class T>
struct ListNode
{ListNode(const T& val = T()):_val(val){}ListNode* _next = nullptr;ListNode* _prev = nullptr;T _val;
};
void push_back(T val)
{insert(end(), val);
}
void insert(iterator pos, T val)
{node* newnode = new node(val);newnode->_next = pos._node;newnode->_prev = pos._node->_prev;pos._node->_prev->_next = newnode;pos._node->_prev = newnode;
}

下面是C++11右值引用版本:通过完美转发forward< T>实现

ListNode(T&& val = T()):_val(std::forward<T>(val))
{}
void push_back(T&& val)
{insert(end(), std::forward<T>(val));
}
void insert(iterator pos, T&& val)
{node* newnode = new node(std::forward<T>(val));newnode->_next = pos._node;newnode->_prev = pos._node->_prev;pos._node->_prev->_next = newnode;pos._node->_prev = newnode;
}

移动构造和移动赋值重载

C++11新增了上面两个默认成员函数。但是默认生成函数的生成条件苛刻:

  • 当你没有实现移动构造,且没有实现析构、拷贝构造、拷贝赋值重载。编译器会生成默认移动构造,后者会对内置类型浅拷贝,对自定义类型调用它的移动构造(如果它没就调用拷贝构造)。
  • 当你没有实现移动赋值重载,且没有实现析构、拷贝构造、拷贝赋值重载。编译器会生成默认移动赋值,后者会对内置类型浅拷贝,对自定义类型调用它的移动赋值(如果它没就调用拷贝赋值)。
  • 如果你实现了移动构造/移动赋值,编译器不会生成默认拷贝构造和拷贝赋值。

总结,移动构造、移动赋值、析构、拷贝构造、拷贝赋值只要有一个实现了,编译器就不会生成默认移动构造/默认移动赋值。
条件也好理解,深拷贝的类肯定要实现析构、拷贝构造、拷贝赋值中至少一个。都不实现,编译器认为这个类不需要深拷贝。

四.小知识

类成员变量初始化

可以在成员变量的声明处给缺省值,用于初始化列表。

委托构造(认识)
可以在构造函数里(初始化列表里和函数体里都可)调用其他构造函数。

五.可变参数模板

模板的可变参数,即模板参数包,像printf里的参数包一样,包含0到任意个模板参数。用法如下:

template<class ...Args>
void ShowSize(Args... args)
{cout << sizeof...(args) << endl;
}
void _Show() { cout << endl; }
template<class T, class ...Args>
void _Show(T&& val, Args&&... args)
{cout << val << " ";_Show(args...);//递归解析参数包
}
template<class ...Args>
void Show(Args&&...args)
{_Show(args...);
}
template<class T>
void PrintArg(T t) { cout << t << " "; }
template<class ...Args>
void show(Args&&... args)
{int arr[] = { (PrintArg(args),0)... };cout << endl;
}
int main()
{Show();Show(1, 'x', "adv");show(1, 'x', "adv");
}

其实,模板参数包在编译时就在参数包arg…处展开成里面的一个个数据。
可变模板参数一个重要应用就是emplace系列接口(C++11后所有容器的每一个插入接口都增添了一个emplace系列接口),下面以list的两个接口为例说明emplace和原本插入接口的效率差别
在这里插入图片描述
大多数场景()两者效率相差不大,但是当push_back发生隐式类型转换时,就有差别了。比如list存string类,同样插入一个"abc",emplace_back只会调用1构造,而push_back要调用1构造匿名对象+1移动构造。因为,前者用模板参数包接收,那么参数包一路往下层层传,直到最后插入时才直接构造string;而后者是单参数类型函数,参数会发生隐式类型转换,所以"abc"在第一层就被构造成匿名string,作为右值一路下传,最后插入时调移动构造。相当于后者只多了一个移动构造😂。
总结:emplace系列大多场景和原本插入接口效率没区别,少数场景优于后者(但移动构造的效率极高,所以差别依然不大),推荐使用emplace系列。
emplace还有一个重要应用,在C++线程创建时用可变模板参数接收函数参数,这样线程传参更加灵活方便。

六.lambda表达式(又称匿名函数)(重要)

格式形如:[capture-list] (parameters)mutable -> return-type { statement }

  • [capture-list] :捕捉列表,不可省略。用来捕捉父作用域,即包含它的作用域的变量。
  • (parameters):参数列表,可省略,但不建议。
  • mutable:翻译为可变的,用于取消参数默认的const属性,可省略。使用时不可省略参数列表。
  • -> return-type:返回值类型,可省略。编译器会自动推导。
  • { statement }:函数体,不可省略。

关于捕捉列表,用法如下:

int a = 0, b = 1, c = 2;
auto f = [&]() {return a + b + c; };//全部传引用捕捉
auto f = [=]() {return a + b + c; };//全部传值捕捉,注意修改时要用mutable
auto f = [&, a]() {return a; };//a传值捕捉,其他传引用捕捉
auto f = [=, &a]() {return a; };//a传引用捕捉,其他传值捕捉

lambda的底层是用仿函数实现的:
lambda底层
可见调用lambda对象时是在调用一个lambda_uuid的对象的仿函数,其中uuid,全称universally unique identifier,是一种唯一标识符,区别开lambda对象。所以lambda对象之间不能互相赋值,因为对象名字都不一样。

七.多线程相关

thread库

linux和windows下的线程相关接口不同,C++11为了支持跨平台编译,整出了线程库。
thread
这里thread的构造使用了可变模板参数,所以线程传参自由灵活。拷贝构造被禁掉了,线程拷贝不如创建一个。
但是,为什么会有无参构造?下面展示一种用法

#include<thread>
//m个线程打印0~n,展示无参构造的一种用法
int main()
{int m; cin >> m;vector<thread>vtd(m);for (int i = 0; i < m; i++){int n; cin >> n;vtd[i] = thread([&]() {//移动赋值for (int j = 0; j < n; j++){cout << i << ":" << j << endl;}});}for (auto&td: vtd)//必须带引用,因为不支持拷贝构造{td.join();}
}

其他接口与posix的那一套接口类似。想要获取线程id时,既可以用thread的get_id接口,也可以用命名空间this_thread里的get_id接口(谁在执行代码,谁打印它的id)。

mutex库

  • 库中mutex类的拷贝构造自然被封禁,常用接口lock与unlock与posix的一致。(try_lock的until和for都是与尝试时间相关,用法简单,自行了解即可,以下不再提until/for类接口)
  • 如果函数内涉及递归,应当使用recursive_mutex,不会有死锁,且接口类似。
  • lock_guard采用RAII(在下一篇博客,智能指针处详细介绍)设计风格,在代码块内自动加锁解锁,可以防止诸如抛异常直接跳转至catch部分导致忘记解锁的问题。模拟实现如下
template<class Lock>
class LockGuard
{
public:LockGuard(Lock& mtx) :_mtx(mtx) { _mtx.lock(); cout << "Locked" << endl; }~LockGuard() { _mtx.unlock(); cout << "UnLocked" << endl; }
private:		//指针接收也可Lock& _mtx;	//必须引用接收,库里mutex禁掉拷贝构造
};
int main()
{mutex mtx;LockGuard<mutex>lg(mtx);
}

类似还有unique_guard,它提供lock/unlock接口可以手动加锁解锁,如果代码块内有相关需求可以使用。

atomic库

如果你嫌加锁解锁太过繁琐,可以了解一下无锁编程,它的其中一种实现方式就是CAS(compare and swap),即对于一个变量,要写入它之前,先比较寄存器里存的旧值和读取的新值是否相等,相等就直接写入,否则说明有别的线程改动了它,那就更新寄存器里的值再操作即可。而且,无论是读取还是写入它,CAS都能保证操作的原子性(atomic),即每个操作都是一句汇编/cpu指令。所以,CAS是一种原子操作。

关于原子操作的个人理解:原子操作就是底层只有一个cpu指令的操作,这样就算线程时间片到了被切走,它要么是操作完了,要么是根本没操作,不存在中间状态,这样避免了最复杂的情况,也就是操作一半被切走的情况。而搭配其他机制诸如CAS等即可基本解决线程安全问题。
关于原子操作的linux接口直接搜难找,可以在源码中<linux/atomic.h>找到。

C++11的atomic类底层实现机制主要是CAS操作,所以使用atomic类无需加锁。基本用法如下:

atomic<int>i{1};//带参构造,还有无参构造(调对应默认构造)
i++;//对被封装的变量原子性++
i.fetch_add(100);//对被封装的变量原子性+
cout << i.load() << endl;//load取出被封装的变量

其余的接口使用见官方文档示例。

condition_variable库

  • condition_variable也是默认无参构造,拷贝构造禁掉。
  • wait和notify_one接口与posix含义一致。wait需要传unique_lock,因为进入wait后,线程要unlock,被notify后,wait会自动帮线程抢锁并lock。需要注意,可能伪唤醒或条件不再满足,所以应使用while套wait,或在wait的第二个参数传可调用对象来判断条件,为真才唤醒,和前者等价。而notify_one也是随即唤醒一个wait的线程,如果没有,就啥也不做,继续向下执行。
    wait
    notify-one
    下面演示一个条件变量控制2线程交替打印奇偶数:
#include<thread>
#include<mutex>
#include<condition_variable>
//双线程交替打印1~100
int main()
{int x = 1;mutex mtx;condition_variable cv;thread t1([&]() {while (x < 100){unique_lock<mutex> ul(mtx);while (x % 2 == 0)cv.wait(ul);cout << "1:" << x << endl;++x;cv.notify_one();}});thread t2([&]() {while (x <= 100){unique_lock<mutex> ul(mtx);while (x % 2 != 0)cv.wait(ul);//就算t2先抢到锁,也会因条件不满足而wait放手cout << "2:" << x << endl;++x;cv.notify_one();}});t1.join();t2.join();
}

八.包装器

function包装器

也叫适配器,就是一个类,可以像函数一样被调用。包装器的初始化就是实例化出一份类来封装可调用对象,包装器的调用也是仿函数,仿函数内再去调用包装的可调用对象。相当于封装了一层,抹除了类型差异,在调用时看起来是一样的。
C++中可调用对象(能像函数一样调用的对象)包括函数指针、仿函数和lambda表达式,但是它们类型不同,想统一使用或者传递时指明类型就很不方便,比如传参时想不用模板来接受一个lambda对象该怎么接收,都写不出来它的类型?为此有了function包装器来统一表示可调用对象的类型,方便统一管理与使用。包装器定义形如function<int(float,double)>func=funcAint是返回值,float和double是参数类型,func就是这个包装器的名字,funcA是可调用对象。
用法如下:

#include<functional>
struct A
{void operator()(int, long) { cout << "()" << endl; }void func(int, long) { cout << "func" << endl; }
};
void f(int, long) { cout << "f" << endl; }
int main()
{A a;function<void(int, long)>f1 = f;function<void(int, long)>f2 = A();function<void(int, long)>f3 = [](int, long) {};function<void(A, int, long)>f4 = &A::func;//指明通过对象调用funcfunction<void(A*, int, long)>f5 = &A::func;//指明通过指针调用funcf4(a, 1, 1);f4(A(), 1, 1);//指明对象调用,匿名对象也可调用funcf5(&a, 1, 1);//f5(A(), 1, 1);//编译不通过,因为右值没法&,就没有指针
}

bind

一个函数模板,通过接收可调用对象来改变它的传参模式。用途有改变参数顺序,改变参数个数等,如下:

#include<functional>
void Print(int a, int b) { cout << a << " " << b << endl; }
struct A
{void func(int a, int b) { cout << a << " " << b << endl; }
};
int main()
{Print(1, 5);auto RPrint = bind(Print, placeholders::_2, placeholders::_1);//后两个是占位符,placeholders是一个命名空间//function<void(int,int)> fPrint = bind(Print, placeholders::_2, placeholders::_1);//后两个是占位符,placeholders是一个命名空间//bind(Print, placeholders::_2, placeholders::_1)(1, 5);RPrint(1, 5);//fPrint(1, 5);bind(&A::func, A(), placeholders::_2, placeholders::_1)(1, 5);//第一个参数绑定成匿名对象,后两个参数顺序互换,注意剩下参数依然从_1开始
}

其实,bind返回的也是一个类对象,后跟()就是调用仿函数,仿函数里调用原来的函数。改变参数顺序就是把你传给它的第参数按占位符传给原来函数的对应位置参数。记住用法即可。

C++11完结,天呐,手打了快1万字,代码块算是stl篇里最少的一次了,终于结束了,眼都麻了现在。就差一个智能指针和异常C++就彻底over了。同志仍需努力啊🥲

相关文章:

C++11

C11 C11简介一.列表初始化{ }initializer_list 二.一些关键字三.右值引用和移动语义&#xff08;重要&#xff09;完美转发移动构造和移动赋值重载 四.小知识类成员变量初始化 五.可变参数模板六.lambda表达式&#xff08;又称匿名函数&#xff09;&#xff08;重要&#xff09…...

MySQL - 表的增删查改

文章目录 1.新增1.1语法1.2单行插入1.3多行插入1.4插入后更新1.5替换 2.查找2.1语法2.2使用 3.修改3.1语法3.2使用 4.删除4.1语法4.2使用4.3截断表 5.插入查询结果5.1语法5.2使用 1.新增 1.1语法 INSERT [INTO] table_name [(column1, column2, ...)] VALUES (value1, value2…...

Vue3 调用子组件的方法和变量

1. 通过 ref 调用子组件的方法和变量 Vue 3 引入了 ref&#xff0c;你可以通过 ref 获取子组件实例&#xff0c;并调用其方法或访问其数据。 例子 子组件 (Child.vue) <template><div><p>{{ message }}</p><button click"updateMessage&qu…...

蓝桥杯嵌入式再学习(4)led的点亮

led的点亮的话先在cubemx里点一下配置 以下是对应的代码...

CentOS7安装nvm

CentOS7安装nvm 在 CentOS 7 上安装 NVM&#xff08;Node Version Manager&#xff09;可以通过以下步骤进行。NVM 是一个用于管理多个 Node.js 版本的工具&#xff0c;允许你在不同的项目中使用不同的 Node.js 版本。 步骤 1&#xff1a;更新系统 首先&#xff0c;确保你的…...

2024年工信部大数据分析师证书报考条件是怎样的?有什么用

大数据分析师&#xff0c;乃是这样一类专业人才&#xff0c;他们凭借着先进且高效的数据分析技术以及各类实用工具&#xff0c;对规模庞大、纷繁复杂的海量数据展开全面而细致的清洗、处理、分析以及解读工作。其工作的核心目标在于为企业的决策制定提供有力依据&#xff0c;推…...

天锐绿盾加密软件与Ping32联合打造企业级安全保护系统,确保敏感数据防泄密与加密管理

随着信息技术的飞速发展&#xff0c;企业在日常经营过程中产生和处理的大量敏感数据&#xff0c;面临着越来越复杂的安全威胁。尤其是在金融、医疗、法律等领域&#xff0c;数据泄漏不仅会造成企业巨大的经济损失&#xff0c;还可能破坏企业的信誉和客户信任。因此&#xff0c;…...

代码随想录算法训练营第六十天|Day60 图论

Bellman_ford 队列优化算法&#xff08;又名SPFA&#xff09; https://www.programmercarl.com/kamacoder/0094.%E5%9F%8E%E5%B8%82%E9%97%B4%E8%B4%A7%E7%89%A9%E8%BF%90%E8%BE%93I-SPFA.html 本题我们来系统讲解 Bellman_ford 队列优化算法 &#xff0c;也叫SPFA算法&#xf…...

Web登录页面设计

记录第一个前端界面&#xff0c;暑假期间写的&#xff0c;用了Lottie动画和canvas标签做动画&#xff0c;登录和注册也连接了数据库。 图片是从网上找的&#xff0c;如有侵权私信我删除&#xff0c;谢谢啦~...

Rust标准库中集合类型用法详解

文章目录 Vec<T> 动态数组创建动态数组增加删除元素访问元素遍历Vec控制容量修改元素元素排序 HashMap<K, V>哈希表创建 HashMap插入和更新元素访问元素删除元素遍历HashMap使用默认值 HashSet<T>哈希集合创建 HashSet插入和删除元素查找元素遍历HashSet使用…...

软件测试面试之数据库部分

1.取第 4 到5 条记录 --按ID从小到大&#xff0c;查询第到第条数据 select top4 *from(select top5 * from qicheorder by ID asc ) as TA order by ID desc--按ID从小到大&#xff0c;查询第到第条数据 select top 2*from(select top 4 *from qicheorder by ID asc )as TA o…...

Gitee markdown 使用方法(持续更新)

IPKISS 获取仿真器件的名称 引言正文标题换行第一种------在行末尾手动键入两个空格第二种------额外换行一次&#xff0c;即两行中间留一个空行 缩进与反缩进代码块行内代码添加图片添加超链接 加粗&#xff0c;倾斜&#xff0c;加粗倾斜 引言 有些保密性的文件或者教程&…...

水库大坝安全监测之量水堰计应用

量水堰计是水库大坝安全监测系统中的一种关键设备&#xff0c;主要用于测量水库水位、流量等水力参数。以下是量水堰计在水库大坝安全监测中的应用及注意事项&#xff1a; 一、量水堰计的工作原理 量水堰计是一种专门用于测量水流流量的仪器&#xff0c;其工作原理主要基于水流…...

Mouser EDI 需求分析

为了提高供应链的自动化水平&#xff0c;贸泽电子&#xff08;Mouser Electronics&#xff09;使用EDI技术更好地管理与其全球合作伙伴之间的业务数据往来。对接Mouser EDI&#xff0c;对于企业而言&#xff0c;需要在本地部署EDI软件&#xff0c;建立与Mouser之间的EDI连接通道…...

51单片机快速入门之中断的应用 2024/11/23 串口中断

51单片机快速入门之中断的应用 基本函数: void T0(void) interrupt 1 using 1 { 这里放入中断后需要做的操作 } void T0(void)&#xff1a; 这是一个函数声明&#xff0c;表明函数 T0 不接受任何参数&#xff0c;并且不返回任何值。 interrupt 1&#xff1a; 这是关键字和参…...

电脑显示器拔插DVI线后副屏不显示

问题&#xff1a;台式机副屏显示器插拔DVI线后副屏无法检测到&#xff0c;不显示 其他现象&#xff1a;电脑设备管理器“显示适配器”中只有独显&#xff0c;未显示集显。 尝试方法&#xff1a; 1、 重新插拔并拧紧DVI线、更换DVI线、将DVI线替换为VGA线、调换DVI线及VGA线两…...

git分支管理:release分支内容重置为master

背景&#xff1a;公司项目存在release和master分支&#xff0c;一直是release合并到master分支&#xff1b;由于历史总总原因导致release和master分支内容相差很大。某个夜晚&#xff0c;leader悄悄改了master分支的内容&#xff08;不走合并流程&#xff09;&#xff0c;然后通…...

python之poetry 安装、创建项目、修改源、创建虚拟环境等操作

CentOs7.5下安装python3&#xff0c;修改源&#xff0c;创建虚拟环境 python 虚拟环境的搭建 使用pyenv 管理多个版本的python 安装 pyenv curl https://pyenv.run | bash pyenv install 3.10 pyenv local 3.10 # 当前项目激活Python3.10 pyenv global 3.10 # 当前全部激活P…...

一个高度可扩展的 Golang ORM 库【GORM】

GORM 是一个功能强大的 Golang 对象关系映射&#xff08;ORM&#xff09;库&#xff0c;它提供了简洁的接口和全面的功能&#xff0c;帮助开发者更方便地操作数据库。 1. 完整的 ORM 功能 • 支持常见的关系模型&#xff1a; • Has One&#xff08;一对一&#xff09; • …...

hadoop_HA高可用

秒懂HA HA概述HDFS-HA工作机制工作要点元数据同步参数配置手动故障转移自动故障转移工作机制相关命令 YARN-HA参数配置自动故障转移机制相关命令 附录Zookeeper详解 HA概述 H(high)A(avilable)&#xff1a; 高可用&#xff0c;意味着必须有容错机制&#xff0c;不能因为集群故障…...

23种设计模式-工厂方法(Factory Method)设计模式

文章目录 一.什么是工厂方法设计模式&#xff1f;二. 工厂方法模式的特点三.工厂方法模式的结构四.工厂方法模式的优缺点五.工厂方法模式的 C 实现六.工厂方法模式的 Java 实现七.代码解析八.总结 类图&#xff1a; 工厂方法设计模式类图 一.什么是工厂方法设计模式&#xff1…...

论文笔记 SliceGPT: Compress Large Language Models By Deleting Rows And Columns

欲买桂花同载酒&#xff0c;终不似&#xff0c;少年游。 数学知识 秩&#xff1a; 矩阵中最大线性无关的行/列向量数。行秩与列秩相等。 线性无关&#xff1a;对于N个向量而言&#xff0c;如果任取一个向量 v \textbf{v} v&#xff0c;不能被剩下的N-1个向量通过线性组合的方式…...

构建 LLM (大型语言模型)应用程序——从入门到精通(第七部分:开源 RAG)

通过检索增强生成 (RAG) 应用程序的视角学习大型语言模型 (LLM)。 本系列博文 简介数据准备句子转换器矢量数据库搜索与检索大语言模型开源 RAG&#xff08;本帖&#xff09;评估服务LLM高级 RAG 1. 简介 我们之前的博客文章广泛探讨了大型语言模型 (LLM)&#xff0c;涵盖了其…...

快速理解倒排索引在ElasticSearch中的作用

一.基础概念 定义&#xff1a; 倒排索引是一种数据结构&#xff0c;用来加速文本数据的搜索和检索&#xff0c;和传统的索引方式不同&#xff0c;倒排索引会被每个词汇项与包含该词汇项的文档关联起来&#xff0c;从而去实现快速的全文检索。 举例&#xff1a; 在传统的全文…...

彻底理解微服务配置中心的作用

常见的配置中心有SpringCloudConfig、Apollo、Nacos等&#xff0c;理解它的作用&#xff0c;无非两点&#xff0c;一是配置中心能做什么&#xff0c;不使用配置中心会出现什么问题。 作用&#xff1a;配置中心是用来集中管理服务的配置&#xff0c;它是用来提高系统配置的维护…...

基于YOLOv8深度学习的智慧农业棉花采摘状态检测与语音提醒系统(PyQt5界面+数据集+训练代码)

智慧农业在现代农业中的应用日益广泛&#xff0c;其核心目标是通过智能化手段实现农业生产的自动化、精准化和高效化&#xff0c;而精准采摘技术作为智慧农业的重要组成部分&#xff0c;正受到越来越多的关注。棉花作为一种经济作物&#xff0c;其采摘过程传统上依赖于人工劳作…...

自动控制原理——BliBli站_DR_CAN

自动控制 2 稳定性分析 极点在左半平面 输入为单位冲击&#xff0c;而拉普拉斯变换为1&#xff1b;因此&#xff0c;开环和闭环系统&#xff0c;研究其传递函数的稳定性就可以了 2.5_非零初始条件下的传递函数_含有初始条件的传递函数 如果一个系统的初始条件不为0&#xff0…...

使用phpStudy小皮面板模拟后端服务器,搭建H5网站运行生产环境

一.下载安装小皮 小皮面板官网下载网址&#xff1a;小皮面板(phpstudy) - 让天下没有难配的服务器环境&#xff01; 安装说明&#xff08;特别注意&#xff09; 1. 安装路径不能包含“中文”或者“空格”&#xff0c;否则会报错&#xff08;例如错误提示&#xff1a;Cant cha…...

vue2 pinia 安装与入门

安装 本体 npm install pinia vue2特定 npm install vue/composition-api 持久化存本地 npm install pinia-plugin-persistvue.config.js 不加的话会报错 configureWebpack: { // 在configureWebpack里加上以下modulemodule: {rules: [{test: /\.mjs$/,include: /node_mo…...

路由传参、搜索、多选框勾选、新增/编辑表单复用

前言&#xff1a; 记录添加运动员页面功能的具体实现 ①由赛事管理页面跳转时路由传参&#xff08;携带该页面表格中莫某条数据对应的赛事id到另一个页面&#xff09;&#xff1b; ②搜索框实时搜索&#xff1b; ③多选框勾选搜索&#xff1b; ④新增表单和编辑表单复用&a…...

内网不出网上线cs

一:本地正向代理目标 如下&#xff0c;本地(10.211.55.2)挂好了基于 reGeorg 的 http 正向代理。代理为: Socks5 10.211.55.2 1080python2 reGeorgSocksProxy.py -l 0.0.0.0 -p 1080 -u http://10.211.55.3:8080/shiro/tunnel.jsp 二&#xff1a;虚拟机配置proxifer 我们是…...

防止按钮被频繁点击

在做开发的时候,不希望按钮被用户频繁点击,给后端服务器增加负担,这个时候,可以在按钮的触发函数加上如下代码: // 禁用按钮 const fetchButton document.querySelector(.btn-fetch); fetchButton.disabled true; // 延时61秒后重新启用按钮 setTimeout(() > { fetchBut…...

Zariski交换代数经典教材Commutative Algebra系列(pdf可复制版)

Zariski的名字估计学代数几何的人都耳熟能详&#xff0c;先是入门时期的交换代数教材&#xff0c;然后就是深入研究时期随处可见的Zariski拓扑。本帖我们分享的便是著名的Zariski交换代数教材。 Oscar Zariski & Pierre Samuel写的交换代数经典教材Commutative Algebra&am…...

【C++】数据类型(上)

C规定在创建一个变量或一个常量时&#xff0c;必须要指定出相应的数据类型&#xff0c;否则无法给变量分配内存 数据类型存在意义&#xff1a;给变量分配合适的内存空间。 1.1 整型 整型作用&#xff1a;整型变量表示的整数类型的数据。 C中能够表示整型类型的有以下几种…...

(C语言) 8大翻译阶段

(C语言) 8大翻译阶段 文章目录 (C语言) 8大翻译阶段⭐前言&#x1f5c3;️8大阶段&#x1f5c2;️1. 字符映射&#x1f5c2;️2. 行分割&#x1f5c2;️3. 标记化&#x1f5c2;️4. 预处理&#x1f5c2;️5. 字符集映射&#x1f5c2;️6. 字符串拼接&#x1f5c2;️7. 翻译&…...

QT QHBoxLayout控件 全面详解

本系列文章全面的介绍了QT中的57种控件的使用方法以及示例,包括 Button(PushButton、toolButton、radioButton、checkBox、commandLinkButton、buttonBox)、Layouts(verticalLayout、horizontalLayout、gridLayout、formLayout)、Spacers(verticalSpacer、horizontalSpacer)、…...

生成式 AI 应用创新引擎dify.ai部署并集成ollama大模型详细图文教程

引言 Dify 是一个开源 LLM 应用开发平台&#xff0c;拥有直观的界面结合了 AI 工作流、RAG 管道、代理功能、模型管理、可观察性功能等&#xff0c;可以快速从原型开发到生产。 Ollama 是一个本地推理框架&#xff0c;允许开发人员轻松地在本地部署和运行 LLM&#xff…...

MySQL闪回恢复:轻松应对数据误删,数据安全有保障

在数据库管理中&#xff0c;数据误删是一个常见且棘手的问题。传统的数据恢复方法可能涉及复杂的操作&#xff0c;如全量备份和增量备份的恢复。MySQL的闪回恢复功能提供了一种更为简便、高效的数据恢复手段。本文将详细介绍MySQL闪回恢复的原理、配置和使用方法&#xff0c;帮…...

面经-综合面/hr面

面经-综合面/hr面 概述1.大学期间遇到的困难&#xff0c;怎么解决的2. 大学期间印象最深/最难忘的是什么3. 大学里面担任了什么职务没&#xff1f;做了什么工作&#xff1f;4. 大学最大的遗憾是什么&#xff1f;5. 对自己的未来规划6. 对自己的评价7. 自己的优缺点8. 对公司的认…...

利用Java爬虫获取阿里巴巴中国站跨境属性的详细指南

在全球化贸易的浪潮中&#xff0c;跨境电商正成为连接全球买家和卖家的重要桥梁。阿里巴巴中国站作为全球领先的B2B电子商务平台&#xff0c;提供了海量的商品信息&#xff0c;其中跨境属性信息对于跨境电商尤为重要。本文将详细介绍如何使用Java编写爬虫&#xff0c;从阿里巴巴…...

Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的 Options Api 有什么不同?

Vue 3.0 引入的 Composition API 和 Vue 2.x 中的 Options API 是两种不同的开发方式。它们在组织和管理组件代码的方式上有很大的差异。虽然两者都能实现相同的功能,但 Composition API 提供了更好的灵活性和可维护性,特别是对于复杂的组件和大型项目。 以下是对比这两种 A…...

电脑中的vcruntime140_1.dll文件有问题要怎么解决?一键修复vcruntime140_1.dll

遇到“vcruntime140_1.dll无法继续执行代码”的错误通常表明电脑中的vcruntime140_1.dll文件有问题。这个文件属于Visual C Redistributable&#xff0c;对很多程序的运行至关重要。本文将提供几个步骤&#xff0c;帮助你迅速修复这一错误&#xff0c;使电脑恢复正常工作状态。…...

【网络安全 | 漏洞挖掘】绕过SAML认证获得管理员面板访问权限

未经许可,不得转载。 文章目录 什么是SAML认证?SAML是如何工作的?SAML响应结构漏洞结果什么是SAML认证? SAML(安全断言标记语言)用于单点登录(SSO)。它是一种功能,允许用户在多个服务之间切换时无需多次登录。例如,如果你已经登录了facebook.com,就不需要再次输入凭…...

技能之发布自己的依赖到npm上

目录 开始 解决 步骤一&#xff1a; 步骤二&#xff1a; 步骤三&#xff1a; 运用 一直以为自己的项目在github上有了&#xff08;之传了github&#xff09;就可以进行npm install下载&#xff0c;有没有和我一样萌萌的同学。没事&#xff0c;萌萌乎乎的不犯罪。 偶然的机…...

python+django5.1+docker实现CICD自动化部署springboot 项目前后端分离vue-element

一、开发环境搭建和配置 # channels是一个用于在Django中实现WebSocket、HTTP/2和其他异步协议的库。 pip install channels#channels-redis是一个用于在Django Channels中使用Redis作为后台存储的库。它可以用于处理#WebSocket连接的持久化和消息传递。 pip install channels…...

GitHub仓库的README添加视频播放链接和压缩视频网站推荐

想在github的README里面添加视频&#xff0c;有限制&#xff0c;不能超过10MB&#xff0c;所以需要压缩&#xff0c;推荐一个超级厉害的压缩工具&#xff0c;我一个30的视频最后压缩到了3M不到&#xff0c;而且清晰度没有变化&#xff0c;视频压缩网站地址&#xff1a;在线减小…...

PHP学习_1

一.PHP基本语法 1.变量 <?php header("Content-type:text/html;charsetutf-8"); $name1"yanxiao"; $age"3";echo "$name1 今年 $age <br>"; echo "$name1 喜欢 xtf <br>"; echo "$name1 不喜欢英语&…...

深入解析 MySQL 启动方式:`systemctl` 与 `mysqld` 的对比与应用

目录 前言1. 使用 systemctl 启动 MySQL1.1 什么是 systemctl1.2 systemctl 启动 MySQL 的方法1.3 应用场景1.4 优缺点优点缺点 2. 使用 mysqld 命令直接启动 MySQL2.1 什么是 mysqld2.2 mysqld 启动 MySQL 的方法2.3 应用场景2.4 优缺点优点缺点 3. 对比分析结语 前言 MySQL …...

Wordcloud也能生成一个,带html的词云图文件吗??

-------------词云图集合------------- 用WordcloudPyQt5写个词云图生成器1.0 WordCloud去掉停用词&#xff08;fit_wordsgenerate&#xff09;的2种用法 通过词频来绘制词云图&#xff08;jiebaWordCloud&#xff09; Python教程95&#xff1a;去掉停用词词频统计jieba.tok…...

D2545电动工具调速专用控制电路芯片介绍【青牛科技】

概述&#xff1a; D2545 是一块频率、占空比可调的脉冲控制电路。可通过调节外接的电阻和电容大小来控制输出频率和占空比&#xff0c;达到控制电机转速的作用。 主要特点&#xff1a; ● 电源电压范围宽 ● 占空比可调 ● 静态功耗小 ● 抗干扰能力强 应用&#xff1a; ● …...