【C++】C++11【上】列表初始化|声明|新容器|右值引用|完美转发|新的类功能

目录

1、 C++11简介

2、 统一的列表初始化

2.1 {}初始化

2.2 std::initializer_list

 3、声明

 3.1 auto和范围for

3.1decltype

3.3 nullptr

 4、新容器

5、 右值引用

5.1左值引用和右值引用

5.2 左值引用与右值引用比较 

5.3 左值和右值引用使用场景及意义

 6、完美转发

7、新的类功能

7.1默认成员函数

7.2强制生成默认函数的关键字default:

7.2禁止生成默认函数的关键字delete:


 C++11特性我分为【上】【下】两部分来写,本文介绍【上】

1、 C++11简介

C++0x C++11 C++ 标准 10 年磨一剑,第二个真正意义上的标准珊珊来迟。相比于 C++98/03 C++11 则带来了数量可观的变化,其中包含了约 140 个新特性,以及对 C++03 标准中 600 个缺陷的修正,这使得 C++11 更像是从 C++98/03 中孕育出的一种新语言。相比较而言, C++11 能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更 强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个 重点去学习 C++11增加的语法特性篇幅非常多,这里没办法一一讲解,所以本文主要讲解实际中比较实用的语法。
小故事:
1998 年是 C++ 标准委员会成立的第一年,本来计划以后每 5 年视实际需要更新一次标准,C ++国际标准委员会在研究 C++ 03 的下一个版本的时候,一开始计划是 2007年发布,所以最初这个标准叫C++ 07 。但是到 06 年的时候,官方觉得 2007 年肯定完不成 C++ 07 ,而且官方觉得 2008年可能也完不成。最后干脆叫 C++ 0x x 的意思是不知道到底能在 07 还是 08 还是 09 年完成。结果 2010年的时候也没完成,最后在 2011 年终于完成了 C++ 标准。所以最终定名为 C++11

2、 统一的列表初始化

2.1 {}初始化

C++98 中,标准允许使用花括号 {} 对数组或者结构体元素进行统一的列表初始值设定。比如:
struct Point
{int _x;int _y;
};int main()
{int array1[] = { 1,2,3,4,5 };int array2[5] = { 0 };Point p = { 1, 2 };return 0;
}
C++11 扩大了用大括号括起的列表 ( 初始化列表 ) 的使用范围,使其可用于所有的内置类型和用户自
定义的类型, 使用初始化列表时,可添加等号 (=) ,也可不添加
class Point
{
public:Point(int x = 0, int y = 0) : _x(x), _y(y){}private:int _x;int _y;
};int main()
{int x = 1;int y{ 2 };//c++11,没必要学,没意义//C++11才支持的花括号列表初始化(容器都可以用{}初始化,数组也适用)int array1[]{ 1, 2, 3, 4, 5 };int array2[5]{ 0 };vector<int> v1{ 1,2,3,4,5 };vector<int> v2 = { 1,2,3,4,5 };list<int> l1{ 1,2,3,4,5 };list<int> l2 = { 1,2,3,4,5 };map<string, int> m{ {"苹果", 1},{"西瓜",3},{"香蕉",2}};//map的每个对象都是pairmap<string, int> m1 = { {"苹果", 1},{"西瓜",3},{"香蕉",2} };//对于类的构造函数的初始化Point p1(1, 2); //正常情况下支持的Point p2{ 1, 2 };Point p3 = { 1, 2 };//c++11中的列表初始化也可用于new表达式int* pa = new int[4] {0};return 0;
}

2.2 std::initializer_list

①、类型(其为一个类模板) 

template<class T> class initializer_list;

②、使用场景

std::initializer_list可以认为是一个容器,其 一般作为构造函数的参数,C++11 STL中的不少容器就增加std::initializer_list 作为参数的构造函数,这样初始化容器对象就更方便了。也可以作为operator=的参数,这样就可以用大括号赋值。
//initializer_list的使用(两种写法)
auto i1 = { 10, 20, 30 }; //the type of i1 is an initializer_list
initializer_list<int> i2 = { 1, 2, 3 };//容器是如何支持这种花括号的列表初始化的呢?
//使模拟实现的vector也支持{}初始化和赋值
/*vector(initializer_list<T>l):_capacity(l.size()), _size(0)
{	//为了讲解,这里假设vector没用指针实现,而是用_capacity,_size实现_array = new T[_capacity];for (auto e : l)_array[_size++] = e;
}*/
//其他容器也类似

注:容器支持花括号列表初始化,本质是增加了一个initializer_list的构造函数,initializer_list可以接收{}列表  


 3、声明

 c++11提供了多种简化声明的方式,尤其是在使用模板时。

 3.1 auto和范围for

C++98 auto 是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局
部的变量默认就是自动存储类型,所以 auto 就没什么价值了。 C++11 中废弃 auto 原来的用法,将
其用于实现自动类型推断。这样要求必须进行显式初始化,让编译器将定义对象的类型设置为初
始化值的类型。
//auto和范围for(熟悉)->简化了代码的写法//auto不能做形参和返回值
//auto func(auto e)
//{}
int main()
{std::map<std::string, std::string> dict = { {"leverage","影响力"}, {"acre", "英亩"} };std::map<std::string, std::string>::iterator it1 = dict.begin();auto it2 = dict.begin();//用auto明显更方便书写了//注:这里当容器存的对象比较大时或这个对象要做深拷贝,如string//最好给引用和const,可以减少拷贝,提高效率for (const auto& e : dict) {//容器支持范围for原理:范围for会被编译器替换成迭代器,则支持迭代器就支持范围forcout << e.first << e.second << endl;//acre英亩\nleverage影响力}//注:auto生成的迭代器是可以当参数进行传参的//因为auto生成对象跟只用类型对象是一样的,即it1与it2是一样的,没有区别   //唯一区别:it2类型是编译器自动推导出来的//auto的优势就是可以把类型比较复杂的地方,简化代码的写法//除了STL的容器可以用范围for用法,数组也可以(原生指针也可以认为是天然迭代器,如vector//string等迭代器就是原生指针int a[] = { 1,2,3,4,5,6 };for (auto e : a){cout << e << " ";}cout << endl;
}

3.1decltype

关键字 decltype 将变量的类型声明为表达式指定的类型
//类型推导,属于RTTI (run time type identification)【了解】
//程序运行时对象的类型识别
int main()
{int a = 10;int b = 20;double c = 10;auto d = a + b;auto e = a + c;//拿到类型名称的字符串cout << typeid(d).name() << endl; //intcout << typeid(e).name() << endl; //doublestring s;cout << typeid(s).name() << endl; //class std::basic_string<char,....>//若想定义一个跟d一样类型的对象//typeid(d).name() f;   //报错,故用decltype//通过对象去推类型decltype(e) g;decltype(e) h;cout << typeid(g).name() << endl; //doublecout << typeid(h).name() << endl; //doublereturn 0;
}

3.3 nullptr


 4、新容器

容器中的一些新方法
如果我们再细细去看会发现基本每个容器中都增加了一些C++11的方法,但是其实很多都是用得比较少的。 比如提供了 cbegin cend 方法返回 const 迭代器等等,但是实际意义不大,因为 begin end也是可以返回 const 迭代器的,这些都是属于锦上添花的操作。
实际上 C++11 更新后,容器中增加的新方法最后用的插入接口函数的右值引用版本。
但是这些接口到底意义在哪?网上都说他们能提高效率,他们是如何提高效率的?
请看下面的右值引用和移动语义的讲解。另外 emplace还涉及模板的可变参数,也需要再继续深入学习后面的知识。

5、 右值引用

5.1左值引用和右值引用

传统的C++语法中就有引用的语法,而C++11中新增了的右值引用语法特性,所以我们之前学习的引用就叫左值引用。无论左值引用还是右值引用,都是给对象取别名。不过左值引用主要给左值取别名,右值引用主要给右值取别名

什么是左值?什么是左值引用?
左值是一个表示数据的表达式 ( 如变量名或解引用的指针 ) 我们可以获取它的地址 + 可以对它赋
值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边 。定义时 const 修饰符后的左
值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名。
// 以下的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;

什么是右值?什么是右值引用?

右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引用返回)等等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。右值引用就是对右值的引用,给右值取别名。

// 以下几个都是常见的右值
10;
x + y;
fmin(x, y);// 以下几个都是对右值的右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);// 这里编译会报错:error C2106: “=”: 左操作数必须为左值
10=1;
x + y = 1;
fmin(x, y) = 1;
需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可
以取到该位置的地址,也就是说例如:不能取字面量 10 的地址,但是 rr1 引用后,可以对 rr1 取地
址,也可以修改 rr1 。如果不想 rr1 被修改,可以用 const int&& rr1 去引用,是不是感觉很神奇,
这个了解一下实际中右值引用的使用场景并不在于此,这个特性也不重要。
double x = 1.1, y = 2.2;
int&& rr1 = 10;
const double&& rr2 = x+y;
rr1 = 20;
rr2 = 5.5;  // 报错

5.2 左值引用与右值引用比较 

 左值引用总结:

1. 左值引用只能引用左值,不能引用右值。
2. 但是 const 左值引用既可引用左值,也可引用右值。(这也说明了我们建议加const的原因之一)
//左值引用不能直接引用右值,const左值引用既可以引用左值,也可引用右值
//int& e = 10;
//int& f = x + y;
const int& e = 10;
const int& f = x + y;
右值引用总结:
1. 右值引用只能右值,不能引用左值。
2. 但是右值引用可以 move 以后的左值。
按照语法,右值引用只能引用右值,但右值引用一定不能引用左值吗?因为:有些场景下,可能 真的需要用右值去引用左值实现移动语义。 当需要用右值引用引用一个左值时,可以通过 move 函数将左值转化为右值 C++11 中, std::move() 函数位于 头文件中,该函数名字具有迷惑性,它 并不搬移任何东西,唯一的功能就是将一个左值强制转化为右值引用,然后实现移动语义
//右值引用只能引用右值,不能引用左值,但可以引用move后的左值
//error C2440: “初始化”: 无法从“int”转换为“int &&”
//message : 无法将左值绑定到右值引用
//int&& mm = a;
int&& mm = move(a);

5.3 左值和右值引用使用场景及意义

前面我们可以看到左值引用既可以引用左值和又可以引用右值(加const才行),那为什么 C++11还要提出右值引用呢?下面我们来看看左值引用的短板,右值引用是如何补齐这个短板的。
左值引用的使用场景:
做参数和做返回值都可以提高效率。
void func1(string s)
{}
void func2(const string& s)
{}
int main()
{string s1("hello world");// func1和func2的调用我们可以看到左值引用做参数减少了拷贝,提高效率的使用场景和价值func1(s1);func2(s1);// string operator+=(char ch) 传值返回存在深拷贝// string& operator+=(char ch) 传左值引用没有拷贝提高了效率s1 += '!';return 0;
}
左值引用的短板:
但是当函数返回对象是一个局部变量,出了函数作用域就不存在了,就不能使用左值引用返回,只能传值返回。例如: string to_string(int value)函数中可以看到,这里只能使用传值返回,传值返回会导致至少 1 次拷贝构造 ( 如果是一些旧一点的编译器可能是两次拷贝构造 )
这里用string中的to_string来说明这个问题:
namespace mz
{string to_string(int value){bool flag = true;if (value < 0){flag = false;value = 0 - value;}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;}
}
int main()
{// 在mz::string to_string(int value)函数中可以看到,这里只能使用传值返回,// 传值返回会导致至少1次拷贝构造(如果是一些旧一点的编译器可能是两次拷贝构造)。string ret1 = mz::to_string(1234);string ret2 = mz::to_string(-1234);cout << ret1 << endl; //1234cout << ret2 << endl; //-1234return 0;
}


右值引用的使用场景:

场景1(简单应用)

template<class T>
void f(T& a)
{cout << "void f(const T& a)" << endl;
}template<class T>
void f(T&& a)
{cout << "void f(const T&& a)" << endl;
}int main()
{int x = 10;//f的左值右值引用的参数不同,故构成函数重载f(x);  //void f(const T& a)  ->匹配左值引用f(10); //void f(const T&& a) ->匹配右值引用return 0;
}

场景2

C++11又将右值区分为:纯右值和将亡值
纯右值:基本类型的常量或者临时对象
将亡值:自定义类型的临时对象

以我们模拟实现的String为例,看看右值引用的应用场景 

class String
{
public:String(const char* str = " "){_str = new char[strlen(str) + 1];strcpy(_str, str);}//s2(s1)String(const String& s){cout <<"String(const String& s)-拷贝构造-效率低" << endl;_str = new char[strlen(s._str) + 1];strcpy(_str, s._str);}//s3(右值-将亡值)String(String&& s):_str(nullptr){//传进来的是个将亡值,反正你都要亡了,我的目的是跟你有一样大的空间//不如把你的空间给我cout << "String(String&& s)-移动拷贝构造-效率高" << endl;swap(_str, s._str);}//s3 = s4String& operator=(const String& s){cout << "String& operator=(const String& s)-拷贝赋值-效率低" << endl;if (this != &s){char* newstr = new char[strlen(s._str) + 1];strcpy(newstr, s._str);delete[] _str;_str = nullptr;}return *this;}//s3 = 右值-将亡值String& operator=(String&& s){cout << "String& operator=(const String&& s)-移动赋值-效率高" << endl;swap(_str, s._str); //直接掠夺s的资源即可,反正你s都要亡了return *this;}//第二个层次的问题//s1 + s2String operator+(const String& s2){String ret(*this);//ret.append(s2._str); //因append我们没有模拟实现,故这里注释掉return ret;	//返回的是右值}//s1 += s2String& operator+=(const String& s2){//this->append(s2);return *this; //返回的是左值}~String(){delete[]_str;}
private:char* _str;
};String f(const char* str)
{String tmp(str);return tmp; // 返回tmp拷贝的临时对象
}int main()
{String s1("左值");String s2(s1);				 //参数是左值//String s3(String("右值"));  //编译器会优化掉String s3(f("右值-将亡值"));	  //参数是右值-将亡值(传给你用,用完我就析构了),但编译器也会优化掉String s4(move(s1));			String s5("zuo值");s5 = s1;String s6("s6");String s7("s7");String s8 = s6 += s7; //拷贝构造String s9 = s6 + s7;  //移动构造return 0;

①、拷贝构造和移动拷贝构造的场景 (可以减少拷贝)

移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不 用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己

 注:正常的左值引用时拷贝构造,而右值引用是移动拷贝构造

 ②、拷贝赋值和移动赋值的场景与①类似(也可以减少拷贝)

③、左值和右值做返回值的场景

 operator+与operator+=的返回值

注:operator+返回的是一个右值,因为既有拷贝构造又有移动构造,编译器会选择最匹配的参数调用,用这个右值构造s9,就会匹配调用移动构造。这里其实是个移动语义。

 总结:

以前我们写的函数总是避免用传值做返回值,因为会有深拷贝,但这里有右值引用后,会有移动构造和移动赋值减少拷贝,即不会深拷贝了,那你想传值返回就传值返回(很便利)

 ④、所有深拷贝类(vector/list/map/set..),都可以加两个右值引用做参数的移动拷贝和移动赋值 

  

总结:

⑤、右值引用做函数参数,减少拷贝 

 

 ⑥、左值引用和右值引用减少拷贝的对比


 6、完美转发

模板中的&& 万能引用

解决:利用完美转发,std::forward 完美转发在传参的过程中保留对象原生类型属性

完美转发实际中的使用场景:
list的模拟实现中
template<class T>
struct ListNode
{ListNode* _next = nullptr;ListNode* _prev = nullptr;T _data;
};
template<class T>
class List
{typedef ListNode<T> Node;
public:List(){_head = new Node;_head->_next = _head;_head->_prev = _head;}void PushBack(T&& x){//Insert(_head, x);Insert(_head, std::forward<T>(x));}void PushFront(T&& x){//Insert(_head->_next, x);Insert(_head->_next, std::forward<T>(x));//复用Insert中可能丢失右值属性,故完美转发}void Insert(Node* pos, T&& x){Node* prev = pos->_prev;Node* newnode = new Node;newnode->_data = std::forward<T>(x); // 关键位置// prev newnode posprev->_next = newnode;newnode->_prev = prev;newnode->_next = pos;pos->_prev = newnode;}void Insert(Node* pos, const T& x){Node* prev = pos->_prev;Node* newnode = new Node;newnode->_data = x; // 关键位置// prev newnode posprev->_next = newnode;newnode->_prev = prev;newnode->_next = pos;pos->_prev = newnode;}
private:Node* _head;
};
int main()
{List<bit::string> lt;lt.PushBack("1111");lt.PushFront("2222");return 0;
}

7、新的类功能

7.1默认成员函数

原来C++类中,有6个默认成员函数:
1. 构造函数
2. 析构函数
3. 拷贝构造函数
4. 拷贝赋值重载
5. 取地址重载
6. const 取地址重载
最后重要的是前 4 个,后两个用处不大。默认成员函数就是我们不写编译器会生成一个默认的。
C++11 新增了两个:移动构造函数和移动赋值运算符重载。
针对移动构造函数和移动赋值运算符重载有一些需要注意的点如下:
①、 如果你没自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任
意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类
型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,
如果实现了就调用移动构造,没有实现就调用拷贝构造。
②、 如果你没自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中
的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内
置类型成员会执行逐成员按字节拷贝自定义类型成员,则需要看这个成员是否实现移动赋
值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。 ( 默认移动赋值跟上面移动构造
完全类似 )
③、 如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。

7.2强制生成默认函数的关键字default:

C++11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原 因这个函数没有默认生成。
①、有拷贝构造导致的编译器无法生成默认构造函数
class A
{
public:A(const int& a):_a(a){}//因为你写了拷贝构造,编译器就不会生成默认构造了//法一、自己写一个默认构造//法二、default:指定编译器显式的生成(C++11做法)A() = default; private:int _a = 10;
};int main()
{A aa1;     //若不用default,则失败A aa2(aa); //成功return 0;
}

②、有拷贝构造导致的编译器无法生成移动构造

我们可以 使用 default关键字显示指定移动构造生成
class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){}Person(const Person& p):_name(p._name), _age(p._age){}Person(Person&& p) = default;
private:string _name;int _age;
};
int main()
{Person s1;Person s2 = s1;Person s3 = std::move(s1);return 0;
}

7.2禁止生成默认函数的关键字delete:

如果能想要限制某些默认函数的生成,在 C++98 中,是该函数设置成 private ,并且只声明补丁
已,这样只要其他人想要调用就会报错。在 C++11 中更简单,只需在该函数声明加上 =delete
可,该语法指示编译器不生成对应函数的默认版本,称 =delete 修饰的函数为删除函数。
class A
{
public:A() = default; //若要求A的对象不能拷贝和赋值(防拷贝)//C++98的做法:只给声明,不给实现,这样别人就无法拷贝对象//缺陷:导致链接不上,且别人可以再类外定义
//	A(const int& a); 
//	A& operator=(const A& aa);//为解决上面缺陷,private限定,类外也无法定义
//private:
//	A(const int& a);
//	A& operator=(const A& aa);//C++11的做法:用delete定义为删除函数A(const int& a) = delete;A& operator=(const A& aa) = delete;A(const int& a):_a(a){}private:int _a = 10;
};int main()
{A aa1;A aa2(aa1);aa1 = aa2;return 0;
}

C++【下】链接:【C++】C++11【下】lambda表达式|thread线程库-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/178892.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PC页面-企业微信扫码登录

vue代码引入企业微信扫码登录 企业微信后台管理配置。前端vue 代码使用的配置信息 项目需求PC端登录需要对接企业微信扫码登录功能。 根据同事研究成果&#xff0c;记录该功能的流程。 前端代码用的是vue。 企业微信后台管理配置。 企业微信后台管理登录连接 1、扫码登录企业…

【vscode远程开发】使用内网穿透实现在公网环境下远程访问

文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 前言 远程…

使用免费 FlaskAPI 部署 YOLOv8

目标检测和实例分割是计算机视觉中关键的任务&#xff0c;使计算机能够在图像和视频中识别和定位物体。YOLOv8是一种先进的、实时的目标检测系统&#xff0c;因其速度和准确性而备受欢迎。 Flask是一个轻量级的Python Web框架&#xff0c;简化了Web应用程序的开发。通过结合Fla…

【年终特惠】基于最新导则下生态环评报告编制技术暨报告篇、制图篇、指数篇、综合应用篇系统性实践技能提升

根据生态环评内容庞杂、综合性强的特点&#xff0c;依据生态环评最新导则&#xff0c;将内容分为4大篇章(报告篇、制图篇、指数篇、综合篇)、10大专题(生态环评报告编制、土地利用图的制作、植被类型及植被覆盖度图的制作、物种适宜生境分布图的制作、生物多样性测定、生物量及…

企业链表(未完成)

文章目录 1. 插入2. 类型转换说明2. 代码实现 1. 插入 // 插入 void insert(LinkList* list, int pos, LinkNode* data) {if (!list || !data)return;if (pos < 0 || pos > list->size)return;LinkNode* curNode &(list->head);for (int i 0; i < pos; i)…

【EI会议征稿】第三届电子信息工程、大数据与计算机技术国际学术会议(EIBDCT 2024)

第三届电子信息工程、大数据与计算机技术国际学术会议&#xff08;EIBDCT 2024&#xff09; 2024 3rd International Conference on Electronic Information Engineering, Big Data and Computer Technology 第三届电子信息工程、大数据与计算机技术国际学术会议&#xff08;…

c++ | 字符串与指针的恩断情仇

我想&#xff0c;c/c中难的不是指针&#xff0c;而是其中的变化&#xff0c;尤其是思维的转变。很多东西 就是容易掉进陷阱。好在&#xff0c;你我都是善于思考的码农&#xff01; 大致情况是这样的&#xff0c;底层<–>c语言<–>c<–>应用 而数据的传输的最…

VCR库编写爬虫程序

VCR库编写一个爬虫程序来爬取图片&#xff0c;代码如下所示&#xff1a; require vcr require open-uri ​ # 使用VCR库录制一次HTTP请求 VCR.use_cassette(vip_crawler) do# 设置主机和端口proxy_host proxy_port # 创建一个HTT理对象proxy URI.parse("http://#{prox…

遥遥领先,免费开源的django4-vue3前后端分离项目

星域后台管理系统前端介绍 &#x1f33f;项目简介 本项目前端基于当下流行且常用的vue3作为主要技术栈进行开发&#xff0c;融合了typescript和element-plus-ui&#xff0c;提供暗黑模式和白昼模式两种主题以及全屏切换&#xff0c;开发bug少&#xff0c;简单易学&#xff0c…

电源管理(PMIC)MAX20428ATIA/VY、MAX20428ATIC/VY、MAX20428ATIE/VY适合汽车ADAS应用的开关稳压器

一、概述 MAX20428是一款高效率、八路输出、低压PMIC。OUT1将输入电源升压至5V&#xff0c;电流高达500mA&#xff0c;而三个同步降压转换器的输入电压范围为3.0V至4.2V&#xff0c;输出电压范围为0.8V至3.9875V&#xff0c;峰值电流分别高达1.3A、1.3A和3.5A。三个300mA pMOS…

阿里云双11优惠活动:新老用户99元服务器和代金券领取攻略

2023阿里云双11优惠活动开启了&#xff0c;轻量2核2G3M带宽服务器87元一年、2核4G4M带宽165元一年&#xff0c;云服务器ECS经济型e实例2核2G3M固定带宽优惠价格99元一年&#xff0c;新老用户同享&#xff0c;并且续费不涨价&#xff0c;第二年99元续费。阿里云个人和企业用户还…

tcp/ip该来的还是得来

1. TCP/IP、Http、Socket的区别 \qquad 区别是&#xff1a;TCP/IP即传输控制/网络协议&#xff0c;也叫作网络通讯协议&#xff0c;它是在网络的使用中的最基本的通信协议。Http是一个简单的请求-响应协议&#xff0c;它通常运行在TCP之上。Socket是对网络中不同主机上的应用进…

vue(32) : win10创建vue2基础前端框架

vue2element-uiaxios 1.创建vue2项目 开发工具为HBuilderX 3.7.3 1.1.新建项目 1.2.普通项目-vue项目(2.6.10) 等待创建项目 2.安装element-ui组件 2.1右键左下角开始图标 2.2.cd进入项目目录,执行安装element-ui npm i element-ui -S 2.3.main.js引入配置 import {Paginat…

vue3+ts 提取公共方法

因为好多页面都会使用到这个效验规则&#xff0c;封装一个校检规则&#xff0c;方便维护 封装前 封装后

C++ 面向对象 学习 优秀教程

油管看视频 沉浸式翻译插件&#xff0c;实现中文字幕&#xff01; 文章目录 Object Oriented Programming (OOP) in C Course Object Oriented Programming (OOP) in C Course https://www.youtube.com/watch?vwN0x9eZLix4 博主&#xff1a;https://www.youtube.com/CodeBeau…

vue指令

在 Vue&#xff0c;除了核心功能默认内置的指令 ( v-model 和 v-show )&#xff0c;Vue 也允许注册自定义指令。它的作用价值在于当开发人员在某些场景下需要对普通 DOM 元素进行操作。 Vue 自定义指令有全局注册和局部注册两种方式。先来看看注册全局指令的方式&#xff0c;通…

Centos8安装yum源时候出现的异常问题及解决方案(保好使)

问题的出现 作者在使用centos8的时候&#xff0c;想安装tree命令&#xff0c;输入了如下的命令&#xff1a; yum install tree 但是却显示了下面的错误&#xff1a; Errors during downloading metadata for repository base: - Curl error (28): Timeout was reached for h…

内涝积水监测仪怎么样?万宾科技城市内涝积水监测的作用

在城市建设发展过程中&#xff0c;道路基础设施的建设永远都占据着重要一席&#xff0c;因为人们出行一旦受阻便会影响城市进展&#xff0c;也会影响经济发展。在城市之中有隧道&#xff0c;下穿式立交桥等容易存积水的地方&#xff0c;一旦出现恶劣暴雨天气&#xff0c;这些地…

无限上下文,多级内存管理!突破ChatGPT等大语言模型上下文限制

目前&#xff0c;ChatGPT、Llama 2、文心一言等主流大语言模型&#xff0c;因技术架构的问题上下文输入一直受到限制&#xff0c;即便是Claude 最多只支持10万token输入&#xff0c;这对于解读上百页报告、书籍、论文来说非常不方便。 为了解决这一难题&#xff0c;加州伯克利…

【C++入门 三】学习C++缺省参数 | 函数重载 | 引用

C入门 三 1.缺省参数1.1 缺省参数概念1.2 缺省参数分类 2. 函数重载2.1 函数重载概念2.2 C支持函数重载的原理--名字修饰(name Mangling) 3.引用3.1引用概念3.2引用特性3.3 常引用3.4 使用场景1. 做参数2. 做返回值 3.5 传值、传引用效率比较3.6引用和指针的区别 4.引用和指针的…