c++11语法特性

c++11

1.c++11发展简介

第一个比较正式的c++标准是1998提出的c++98标准。之后定了5年计划,每5年来一次大更新。在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于C++03(TC1)主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。 从C++0x到C++11,C++标准10年磨一剑,第二个真正意义上的标准珊珊来迟。相比C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多。

2.列表初始化

​ 总结:对于自定义类型,1.可以使用花括号传参直接调用构造;2.也可以用花括号构造initializer_list对象,然后在调用使用initializer_list对象的构造或者赋值;对于内置类型使用花括号直接传参构造;

2.1{}初始化

​ 在C++98中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。

即一切皆可以使用花括号初始化,并且可以不写等号。这样就可以支持多参数的隐式类型转换,减少使用匿名对象进行构造;主要是为了支持多参数的构造。

2.2initializer_list

​ 类模板,存放的是常量区数组,不支持写。底层设计是存放了两个const T*指针start(指向开始)和finish(指向最后一个位置的下一个位置),注意不是连续的空间,所以类对象的大小是8。

template<class T> class initializer_list;
//
const int* ptr = { 1,2,3 };//不支持,因为右边会被识别成initializer_list<T>对象,无法进行转换

​ 各种容器都支持initializer_list类对象的构造函数,进行初始化;赋值也支持了initializer_list类对象;

3.声明

3.1auto

​ c++11提供了多种简化声明的方式,尤其是在使用模板时。auto用于定义变量

​ 在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以auto就没什么价值了。C++11中废弃auto原来的用法,将其用于实现自动类型推断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型。

3.2decltype

​ 用于声明变量,不需要定义,关键字decltype将变量的类型声明为表达式指定的类型;

​ 还可以声明函数指针类型变量decltype(malloc) pf,或者用来进行模板实例化B<decltype(变量名)>;

​ decltype还可以与lambda表达式配合着使用;

template<class T1, class T2>
void F(T1 t1, T2 t2)
{decltype(t1 * t2) ret;cout << typeid(ret).name() << endl;
}
int main()
{const int x = 1;double y = 2.2;decltype(x * y) ret; // ret的类型是doubledecltype(&x) p;      // p的类型是int*cout << typeid(ret).name() << endl;cout << typeid(p).name() << endl;F(1, 'a');return 0;
}

3.3nullptr

​ 由于C++中NULL被定义成字面量0,这样就可能回带来一些问题,因为0既能指针常量,又能表示整形常量。所以出于清晰和安全的角度考虑,C++11中新增了nullptr,用于表示空指针。

#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

4.范围for

​ 除了原生数组是使用的指针,其他类型被替换成了迭代器

5.STL新变化

5.1新容器

​ c++11新增了array、forward_list、unordered_map、unordered_set这些容器;

​ array唯一的优势就是强制越界检查,较为鸡肋;

​ forward_list只支持了头插头删,不支持尾插尾删,因为尾插,尾删要找前一个位置,效率低,insert和erase也只是支持了当前位置的后一个位置插入删除;真正使用的意义可能就是哈希桶的子结构,但是实现起来并不复杂,所以这个结构也是较为冗余;

在这里插入图片描述

5.2新接口

​ 1.关于迭代器,const版本的迭代器都加了cbegin类似这种风格,较为鸡肋;

2.提供了使用initializer_list对象进行初始化和赋值;

​ 3.还增加了一些个性化接口,如缩容等;

4.所有的容器都提供了emplace系列的接口,涉及到了右值引用和模板的可变参数;好处就是有了较大的性能提升

5.所有的容器都提供了移动构造和移动赋值版本;使得深拷贝的性能提高了90%;

6.右值引用和移动语义

​ const左值对象既可以引用左值属性,又可以引用右值属性,但是不可以修改,而右值引用的出现就是为了可以修改这种具有常性的临时对象,这样就可以支持移动构造,使得平时深拷贝的临时对象或者将亡对象的资源让别的变量获取;

6.1左值引用和右值引用

什么是左值?什么是左值引用?

​ 左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址,一般可以对它赋值,左值可以出现赋值符号的左边或者右边,右值不能出现在赋值符号左边。定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名。

​ 常用如:指针变量、解引用指针变量,普通变量,const变量

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

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

​ 常用如:字面常量:10、表达式返回值、函数返回值、临时对象也是右值,对于"xxx",被编译器识别成了首元素的地址,所以可以&“xxx”,即常量字符串是左值;

​ 以前使用的引用都是左值引用,语法上不开空间,取别名;

​ 左值引用:就是给左值取别名,右值引用:就是给右值取别名;

6.2右值引用的使用

​ const&既可以引用左值又可以引用右值,权限的缩小或者平移,即左值引用是可以引用右值的,但是右值引用一般是不可以引用左值的,使用move之后就可以了,但是会带来一些影响;

​ 左值引用存在缺陷,局部对象不能引用返回,即必须是拷贝返回,但是要解决深拷贝的问题,使用移动拷贝(资源只产生了一份),移动拷贝对于浅拷贝没有意义;

​ 一般将内置类型的右值叫做:纯右值,自定义类型的右值叫做:将亡值;

​ 场景一:传值返回;

​ 右值引用使用移动拷贝,将右值的资源拿来,如果是移动赋值将本身的资源交给右值,让它析构,移动构造将自身置为空,即使用移动拷贝比深拷贝代价小;

​ 以前传值返回与传值接收是两次深拷贝,使用移动拷贝之后就变成了深拷贝加移动拷贝;经过编译器优化之后就变成了一次移动拷贝;编译器优化了两次,第一次优化成了一次拷贝构造,第二次优化是将局部变量识别成右值,本来是左值;

对于识别成左值就会走拷贝构造,识别成右值就会走移动构造,被move之后进行构造,就会将被move的值识别成右值

int&&a=10;

​ 场景二:作为参数。

​ list<string>,外界push_back (string对象时)每一个节点的构造都会调用string的深拷贝,如果使用右值引用,进行移动拷贝只使用一个资源,可以很好的利用空间;

​ 移动语义就是利用右值实现移动构造和移动赋值;

7.完美转发forward<T>(t)

​ 模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力,但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值,即int&&a=move(b),a的属性是左值,move(b)的属性是右值,实际上a开辟了空间可以支持修改;

​ 我们希望能够在传递过程中保持它的左值或者右值的属性,使用完美转发 std::forward<T>(t)在传参的过程中保持了t的原生类型属性。

​ 实参是左值则进行引用折叠;

7.1完美转发的使用场景

​ 有的地方需要使用左值属性如:传参修改,而有的地方需要使用右值属性如:继续多层函数传参实现移动语义;

​ 右值引用右值,但是需要能够对引用的值进行修改或者给左值函数进行传参,所以默认保证了右值引用变量是左值属性;如果右值引用变量作为参数需要调用移动构造,但是本身是左值属性的,这是就需要使用完美转发,保持右值属性,才能调用到移动构造,否则调用的就是深拷贝;

​ 总结:c++11之后使用右值引用,类模板里面的函数就需要写成函数模板使用万能引用,每一个要传递的值使用forward<T>(变量),如果仅仅是当前使用则不需要加完美转发;

8.lambda表达式

​ 用来替代函数指针,甚至是某些场景下用来替代仿函数;

​ lambda是一个匿名函数的对象,用固定的语法就不需要写专门的仿函数类再实例化对象了;

​ 最好的使用场景就是和线程进行配合;

vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2, 3 }, { "菠萝", 1.5, 4 } };
sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._price < g2._price; });
sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._price > g2._price; });
sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._evaluate < g2._evaluate; });
sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._evaluate > g2._evaluate; });

8.1对比不同的函数可调用对象

1.函数指针,能不用就不用,因为使用起来较为复杂

​ 返回值类型(*函数指针变量名)(参数)

2.仿函数,可以使用,较为麻烦的点就是,每次需要时都需要写一个类,并且使用时需要实例化对象,使用时较为"“重”;

​ 类 重载operator(), 对象可以像函数一样使用;

3.lambda表达式,是一个匿名的函数对象

​ 直接在函数的内部使用;

8.2lambda表达式语法

lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type { statement }

​ []:捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用;

​ ():参数列表,与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略;

​ mutable :默认情况下,lambda函数总是一个const函数,mutable可以取消其常量

性。使用该修饰符时,参数列表不可省略(即使参数为空)。主要的使用场景就是捕获列表的拷贝值可以修改;

​ ->:返回值类型,用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。一般都不需要写返回值,除非进行强制类型转换;

​ {}:函数体:在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。

​ 在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为空。因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情。

​ 对于局部域内,想要使用lambda外部的对象,但是又不通过传参的方式使用,需要将其捕获到捕获列表,而全局域的函数和对象是可以使用的;

8.2.1捕获列表的使用方式

​ [var]:表示值传递方式捕捉变量var,是一种拷贝 ;

​ [=]:表示值传递方式捕获所有父作用域中的变量(包括this) ;

​ [&var]:表示引用传递捕捉变量var ,包括const引用,注意并不是以前的取地址;

​ [&]:表示引用传递捕捉所有父作用域中的变量(包括this),包括const引用 ;

​ [this]:表示值传递方式捕捉当前的this指针 ;

可以组合使用如:[&,a],[=,a],前面是默认设置,后面是显式捕获;

注意:

a. 父作用域指包含lambda函数的语句块 ;

b. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量 ,[&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量 ;

c. 捕捉列表不允许变量重复传递,否则就会导致编译错误。比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复 ;

d. 在块作用域以外的lambda函数捕捉列表必须为空;

e. 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错,即在全局定义时,捕获列表必须为空;

f. lambda表达式之间不能相互赋值,即使看起来类型相同,但是生成的类是不一样的 ;

8.3底层实现

​ lambda表达式的底层就是仿函数;类型时lambda+uuid字符串,uuid时通用唯一识别码,是使用一种算法生成的一个字符串;

​ 其实捕捉列表就是调用了构造,将捕获的变量都生成了默认const成员变量,mutable之后就没有加const修饰;

9.模板可变参数

​ 总结一下:1.函数包的展开方式需要嵌套调用其他函数来完成;2.最大的价值就是作为中间函数一次性接收所有参数,一次性传递所有参数;

​ printf系列函数就是使用了可变参数;可变模板参数不是使用数组的方式实现的;

​ C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板,相比C++98/03,类模版和函数模版中只能含固定数量的模版参数,可变模版参数无疑是一个巨大的改进。

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}
//查看参数包里面参数的个数
sizeof...(args);

​ 上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特点,也是最大的难点,即如何展开可变模版参数。由于语法不支持使用args[i]这样方式获取可变参数,所以我们的用一些奇招来一一获取参数包的值。

9.1递归方式展开参数包

​ 递归编译,最后形成的结果还是按照递归编译的顺序来的;

// 递归终止函数
template <class T>
void ShowList(const T& t)
{cout << t << endl;
}
//对于结束函数可以写一个无参的非函数模板,只需要函数名相同即可
void ShowList()
{cout << endl;
}
// 展开函数
template <class T, class ...Args>
void ShowList(T value, Args... args)
{cout << value <<" ";ShowList(args...);//这样传递的就是所有的参数
}
int main()
{ShowList(1);ShowList(1, 'A');ShowList(1, 'A', std::string("sort"));return 0;
}

9.2逗号表达式展开参数包

​ 逗号表达式执行的结果是最后一部分,即借用数组的初始化来完成展开;

template <class T>
void PrintArg(T t)
{cout << t << " ";
}
//展开函数
template <class ...Args>
void ShowList(Args... args)
{int arr[] = { (PrintArg(args)/*此处是传递的一个值*/, 1)... };//后面的...是其他参数,本质上使用的是多参数的构造;cout << endl;
}
int main()
{ShowList(1);ShowList(1, 'A');ShowList(1, 'A', std::string("sort"));return 0;
}

9.3使用子函数的方式展开参数包

template <class T>
void _ShowList(const T& t)
{cout << t << endl;
}
template <class T, class ...Args>
void ShowList(T value, Args... args)
{cout << value <<" ";ShowList(args...);
}
template <class ...Args>
void ShowList(Args... args)
{_ShowList(args...);
}
int main()
{ShowList(1);ShowList(1, 'A');ShowList(1, 'A', std::string("sort"));return 0;
}

10.包装器

10.1fuction

​ function包装器,也叫作适配器。C++中的function本质是一个类模板,也是一个包装器。;

​ 有了包装器之后就可以统一类型可以用于,将函数调用对象存放到容器中,这样使用调用对象时就可以去容器中进行查找;

​ 包装器解决了调用对象的类型问题,统一了调用对象的类型,使得容器中存放的都是类模板实例化之后的包装器类型;

std::function在头文件<functional>
// 类模板原型如下
template <class T> function;     // undefined
template <class Ret, class... Args>
class function<Ret(Args...)>;//function<返回值(可变参数列表)>
模板参数说明:
Ret: 被调用函数的返回类型
Args…:被调用函数的形参

​ 存在一个指令对应一个动作的场景,即使用map<string,包装器实例化出来的对象>;

10.2bind

​ std::bind函数定义在头文件中,是一个函数模板,它就像一个函数包装器(适配器)**,**接受一个可调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表。

​ 即bind是用来调整参数的(数量和参数方面的);

​ placeholder(占位符),placeholders命名空间内存放了_n参数,按被包装函数的参数列表顺序,分别代表着第1个参数…,调整_n顺序,则可以调整参数顺序;

template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
// with return type (2) 
template <class Ret/*函数返回值调整*/, class Fn/*可调用对象*/, class... Args/*调用对象的参数包*/>
/* unspecified */ bind (Fn&& fn, Args&&... args);
double ala(int x, int y,double rate)
{return (x + y) / rate;
}
function<double(int,int)> f1 =  bind(ala,placeholders::_1,placeholders::_2,4.3);
//1.不写_2 _3是因为按照的是函数的实参来的,固定的数就不参与排序
//2.绑定类的静态员函数要加类名::,如果是普通成员函数需要&Sub::sub,即在类名前面加&,但是要注意其实普通成员函数还有隐含的this指针,所以要定义一个对象,然后把对象地址传入,或者直接传对象/匿名对象;
function<double(int,int)> f1 =  bind(ala,4.3,placeholders::_1,placeholders::_2);
10.2.1bind的底层实现

​ 和lambda类似,底层实现是一个仿函数,传入对象是用对象调用函数,传入对象地址是用指针进行调用;

11.emplace/emplace_back函数

​ 与push_back效率其实相差不大,真正的意义是对于多层复杂结构可以将参数包传到最底层,调用构造,而push_back则会是用对象调用拷贝;

emplace_back(make_pair(1,2));//右值调用移动语义拷贝构造
emplace_back({1,2});//右值调用移动语义构造
emplace_back(1,2);//直接将参数包传递给构造函数构造

在这里插入图片描述

12.新的类功能

12.1默认成员函数

​ c++11类一共有8个默认成员函数,增加了移动构造和移动赋值;

对于这两个函数,如果是深拷贝则需要自己实现移动构造和移动赋值,如果是浅拷贝编译器生成的默认拷贝构造即可满足要求;

对于编译器自动生成的移动构造:

​ 如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个(其实需要自己实现析构,拷贝构造,拷贝赋值重载,那么说明这个类的对象需要在堆上开空间,是一个深拷贝的对象)。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝(浅拷贝),自定义类型成员,则需要看这个成员是否实现移动构造,如果实现了就调用移动构造,没有实现就调用拷贝构造。

对于编译器自动生成的移动赋值:

​ 默认移动赋值跟与默认移动构造完全类似;

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

​ C++11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以使用default关键字显示指定移动构造生成。

Person(Person&& p) = default;

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

​ 如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且只是声明补丁而已,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。

Person(const Person&p) = delete;

12.2类成员变量初始化

​ C++11允许在类定义时给成员变量初始缺省值,默认生成构造函数会使用这些缺省值初始化;

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

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

相关文章

工作中Git如何切换远程仓库地址

工作中Git如何切换远程仓库地址 部门之前的仓库不用了&#xff0c;重新建了一个仓库&#xff0c;但是上传代码还是上传到了之前的仓库里面了&#xff0c;所以得进行修改&#xff0c;下面将修改地址的方法进行操作。 方法一、直接修改远程仓库地址 查看当前远程仓库地址 git …

使用 ChatGPT 写高考作文

写作文&#xff0c;很简单&#xff0c;但写一篇好的作文&#xff0c;是非常有难度的。 想要写一篇高分作文&#xff0c;需要对作文题目有正确的理解&#xff0c;需要展现独到的观点和深入的思考&#xff0c;需要具备清晰的逻辑结构&#xff0c;需要准确而得体的语言表达。 正…

【Linux进阶之路】HTTPS = HTTP + S

文章目录 一、概念铺垫1.Session ID2.明文与密文3.公钥与私钥4.HTTPS结构 二、加密方式1. 对称加密2.非对称加密3.CA证书 总结尾序 一、概念铺垫 1.Session ID Session ID&#xff0c;即会话ID&#xff0c;用于标识客户端与服务端的唯一特定会话的标识符。会话&#xff0c;即客…

LeetCode 热题 100 | 回溯(二)

目录 1 39. 组合总和 2 22. 括号生成 3 79. 单词搜索 菜鸟做题&#xff0c;语言是 C&#xff0c;感冒快好版 关于对回溯算法的理解请参照我的上一篇博客&#xff1b; 在之后的博客中&#xff0c;我将只分析回溯算法中的 for 循环。 1 39. 组合总和 题眼&#xff1a;c…

15届蓝桥杯第二期模拟赛题单详细解析

文章目录 &#x1f9e1;&#x1f9e1;t1_求余&#x1f9e1;&#x1f9e1;思路代码 &#x1f9e1;&#x1f9e1;t2_灌水&#x1f9e1;&#x1f9e1;思路代码 &#x1f9e1;&#x1f9e1;t3_字符显示&#x1f9e1;&#x1f9e1;思路代码 &#x1f9e1;&#x1f9e1;t4_区间最大和…

网络计算机

TCP/IP四层模型 应用层&#xff1a;位于传输层之上&#xff0c;主要提供两个设备上的应用程序之间信息交换的服务&#xff0c;它定义了信息交换的格式&#xff0c;消息会交给下一层传输层来传递。我们把应用层交互的数据单元称为报文。应用层工作在操作系统的用户态&#xff0…

YOLOv8_pose-Openvino和ONNXRuntime推理【CPU】

纯检测系列&#xff1a; YOLOv5-Openvino和ONNXRuntime推理【CPU】 YOLOv6-Openvino和ONNXRuntime推理【CPU】 YOLOv8-Openvino和ONNXRuntime推理【CPU】 YOLOv7-Openvino和ONNXRuntime推理【CPU】 YOLOv9-Openvino和ONNXRuntime推理【CPU】 跟踪系列&#xff1a; YOLOv5/6/7-O…

Android 音频系统

导入 早期Linux版本采用的是OSS框架&#xff0c;它也是Unix及类Unix系统中广泛使用的一种音频体系。 ALSA是Linux社区为了取代OSS而提出的一种框架&#xff0c;是一个源代码完全开放的系统(遵循GNU GPL和GNU LGPL)。ALSA在Kernel 2.5版本中被正式引入后&#xff0c;OSS就逐步…

C语言:操作符详解(下)

目录 一、逗号表达式二、下标访问[ ]、函数调用()1. [ ]下标引用操作符2.函数调用操作符 三、结构成员访问操作符1.结构体(1) 结构的声明(2) 结构体变量的定义和初始化 2.结构成员访问操作符(1)结构体成员的直接访问(2)结构体成员的间接访问 四、操作符的属性&#xff1a;优先级…

Rudolf and the Ball Game

传送门 题意 思路 暴力枚举每一个妆台的转换条件 code #include<iostream> #include<cstdio> #include<stack> #include<vector> #include<algorithm> #include<cmath> #include<queue> #include<cstring> #include<ma…

【Docker】容器的生态系统

Docker提供了一整套技术支持&#xff0c;包括核心技术、平台技术、支持技术。 核心技术 容器核心技术是指能让Container&#xff08;容器&#xff09;在host&#xff08;集群、主机&#xff09;上运行起来的那些技术。 1&#xff09;容器规范&#xff1a;OCI&#xff08;runt…

搭建mysql主从复制(主主复制)

1&#xff1a;设主库允许远程连接(注意&#xff1a;设置账号密码必须使用的插件是mysql_native_password&#xff0c;其他的会连接失败) #切换到mysql这个数据库&#xff0c;修改user表中的host&#xff0c;使其可以实现远程连接 mysql>use mysql; mysql>update user se…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的零售柜商品检测软件(Python+PySide6界面+训练代码)

摘要&#xff1a;开发高效的零售柜商品识别系统对于智能零售领域的进步至关重要。本文深入介绍了如何运用深度学习技术开发此类系统&#xff0c;并分享了全套实现代码。系统采用了领先的YOLOv8算法&#xff0c;并与YOLOv7、YOLOv6、YOLOv5进行了性能比较&#xff0c;呈现了诸如…

蓝桥杯每日一题:血色先锋队

今天浅浅复习巩固一下bfs 答案&#xff1a; #include<iostream> #include<algorithm> #include<cstring>using namespace std; typedef pair<int,int> PII;const int N510; int n,m,a,b; int dist[N][N]; PII q[N*N]; int hh0,tt-1;int dx[]{1,0,-1,…

网络层:地址解析协议ARP、网际控制报文协议ICMP、虚拟专用网络VPN、网络地址转换NAT

文章目录 地址解析协议ARP解决的问题ARP解析流程ARP高速缓存 网际控制报文协议ICMPICMP报文的种类ICMP差错报告报文ICMP询问报文 ICMP应用举例分组网间探测PING(Packet InterNet Groper)traceroute(tracert)确定路径的MTU 虚拟专用网络专用地址虚拟专用网络远程接入VPN(remote …

某鱼弹幕逆向

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018…

mysql题库详解

1、如何创建和删除数据库&#xff1f; 创建数据库 CREATE DATABASE 数据库名; 删除数据库 drop database 数据库名; 2、MyISAM与InnoDB的区别&#xff1f; 1&#xff09;事务&#xff1a;MyISAM 不支持事务 InnoDB 支持 2&#xff09;行锁/表锁&#xff1a;MyISAM 支持表级锁…

Redis中AOF数据持久化

AOF介绍 AOF&#xff08;Append Only File&#xff09;持久化&#xff1a;以独立日志的方式存储了 Redis 服务器的顺序指令序列&#xff0c;并只记录对内存进行修改的指令。 当Redis服务发生雪崩等故障时&#xff0c;可以重启服务并重新执行AOF文件中的指令达到恢复数据的目的…

SpringMVC | SpringMVC中的 “数据绑定”

目录: “数据绑定” 介绍1.简单数据绑定 :绑定 “默认数据” 类型绑定 “简单数据类型” 类型 &#xff08;绑定Java“基本数据类型”&#xff09;绑定 “POJO类型”绑定 “包装 POJO”“自定义数据” 绑定 :Converter (自定义转换器) 2.复杂数据绑定 :绑定数组绑定集合 作者简…

ubuntu 18.04安装教程(详细有效)

文章目录 一、下载ubuntu 18.04镜像二、安装ubuntu1. 点击下载好的Vmware Workstation&#xff0c;点击新建虚拟机&#xff0c;选择 “自定义(高级)”&#xff0c;之后下一步。2. 默认配置&#xff0c;不需要更改&#xff0c;点击下一步。3. 选择 “安装程序光盘映像文件(iso)(…