这是我在学习过程中的总结,代码只写了关键部分,直接复制可能运行不了,还需要额外补充main和头文件等一些东西。可能会有不全或者错误的地方,欢迎大家指出来,共同进步。
STL(Standard Template Library),即标准模板库,是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构。
STL有两个极为重要的特点。1、它不是面向对象的。2、数据结构和算法分离。为了实现泛型编程和更好的通用性,STL依赖于模板而不是OOP的三要素(继承、封装和多态)。
STL从广义上分为:容器、算法和迭代器。容器和算法之间通过迭代器进行无缝连接,STL几乎所有的代码都采用了模板类和模板函数,使得一个数据结构或者算法可以适用于多种类型的数据。
STL中有六大组件:
STL中的容器分类序列式容器和关联式容器。
(1)序列式容器,顾名思义就是有顺序的容器,这种顺序与元素的具体的值无关,由其进入容器的顺序有关。例如vector、list、的确等。
(2)关联式容器,顾名思义就是元素之间具有某种关联,这种所谓的“关联”就是容器内各个元素排序的“规则”,与元素的插入顺序无关。例如元素大小顺序就是一种排序规则。例如set、multiset、map、multimap等。
要访问容器中的元素,需要通过“迭代器(iterator)”进行。迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。
迭代器重载了*,++,==,!=,=运算符。用以操作复杂的数据结构,容器提供迭代器,算法使用迭代器;常见的一些迭代器类型:正向迭代器(iterator)、常量正向迭代器(const_iterator)、反向迭代器(reverse_iterator)和常量反向迭代器(const_reverse_iterator)。
STL定义了一组泛型算法:因为它们是操作数据元素实现某种目的,所以称之为“算法”;而“泛型”指的是它们可以适用于多种容器类型,不但可以作用于标准库类型,也可以用于内置类型。
使用算法需要包含头文件<algorithm>,<numeric>和<functional>。其中<algorithm>是所有STL头文件中最大的一个,是由一大堆模版函数组成的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。
<numeric>只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。
<functional>中定义了一些模板类,用以声明函数对象。
STL中算法大致分为四类:
非可变序列算法:指不直接修改其所操作的容器内容的算法。
可变序列算法:指可以修改它们所操作的容器内容的算法。
排序算法:对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作。
数值算法:对容器内容进行数值计算。
具体分类及使用方法如下:
(1)常用查找算法
bool operator==(const 类名& p) const
{
return 0;
}
(2)常用遍历算法
(3)常用删除和替换算法
重载函数调用操作符“()”的类,其对象称之为函数对象(function object),即它们是香行为类似函数的对象,也叫仿函数(functor),其实就是重载“()”操作符,使得类对象可以像函数那样调用。
注意:
int sortFunc(int v1, int v2)
{
return v1 > v2;
}
void main()
{
//实现vector的降序排列
vector<int> v = {
54, 21, 11, 67, 22 };
sort(v.begin(), v,end(), sortFunc);
}
class MyCompare
{
public:
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
void main()
{
//实现vector的降序排列
vector<int> v = {
54, 21, 11, 67, 22 };
MyCompare mycompare;
sort(v.begin(), v.end(), mycompare);
}
STL内建了一些仿函数,分为:1)算数类仿函数,2)关系运算类仿函数,3)逻辑运算类仿函数。要使用这些内建仿函数,需要包含头文件头文件是<functional>。
例子:
int main()
{
cout << plus<int>()(3, 5) << endl;//3+5
cout << multiplies<int>()(3, 5) << endl;//3*5
}
例子:
int main()
{
vector<int> v = {
54, 21, 11, 67, 22 };
//降序排列
sort(v.begin(), v.end(), greater<int>());
}
(函数对象)适配器是完成一些配接工作,这些配接工作包括绑定(bind),否定(negate)以及对一般函数或成员的修饰,使其成为函数对象:
例子:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
//---------------------绑定适配器bind1st bind2nd---------------------
class MyPrint : public binary_function<int,int,void>
{
public:
void operator()(int v, int val) const
{
cout << v + val << " ";
}
};
void test01()
{
vector<int> v;
for (int i = 0; i < 20; i++)
{
v.push_back(i);
}
//绑定适配器bind2nd,将两个参数绑定为一个参数
int addnum = 100;
for_each(v.begin(), v.end(), bind2nd(MyPrint(),addnum));
//假设要使vector的每个值加一个值addnum后输出,需要用到bind2nd适配器
//操作步骤:
//1、仿函数public继承一个类binary_function<参数一类型,参数二类型,返回类型>
//(MyPrint有两个参数,所以binary_function有两个参数类型+返回类型void)
//2、operator()加入const修饰符
//bind1st和bind2nd的区别?
//bind1st,将addnum绑定为第一个参数
//bind2nd,将addnum绑定为第二个参数
}
//-------------------------取反适配器not1 not2----------------------------
class MyCompare : public binary_function<int, int, bool>
{
public:
bool operator()(int v1, int v2) const
{
return v1 > v2;
}
};
void test02()
{
vector<int> v;
for (int i = 0; i < 20; i++)
{
v.push_back(i);
}
//使vector降序排列
sort(v.begin(), v.end(), MyCompare());
//对MyCompare取反,使得vector升序排列
sort(v.begin(), v.end(), not2(MyCompare()));
//将函数对象取反
//操作步骤:
//1、public继承类binary_function<参数一类型,参数二类型,返回类型>
//(MyCompare有两个参数,所以binary_function有两个参数类型+返回类型bool)
//2、operator()加入const修饰符
//not1 和 not2 的区别
//对二元函数对象取反,用not2
//对一元函数对象取反,用not1
//用not1时,继承的类是unary_function
}
//---------------------普通函数转函数对象ptr_fun----------------------
void MyPrint(int val, int val2)
{
cout << val << " ";
cout << "增加的参数:" << val2 << " ";
}
void test03()
{
vector<int> v;
for (int i = 0; i < 20; i++)
{
v.push_back(i);
}
for_each(v.begin(), v.end(), MyPrint);
//上面for_each调用的是普通函数MyPrint,不是函数对象不能进行绑定
//使用ptr_fun将普通函数转成函数对象,然后可以绑定参数
//此时,MyPrint函数可以增加一个参数
for_each(v.begin(), v.end(), bind2nd(ptr_fun(MyPrint),10));
}
//-----------------成员函数适配器mem_fun mem_fun_ref---------------------
class Person
{
public:
Person(int age, int id) :age(age), id(id)
{
}
void show()
{
cout << "age: " << age << " id: " << id << endl;
}
private:
int age;
int id;
};
void test04()
{
//如果容器中存放着对象或者对象指针,我们可以在for_each中调用对象自己提供的打印函数
vector<Person> v;
Person p1(10, 20), p2(30, 40), p3(50, 60);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
//使用mem_fun_ref可以调用对象内部的成员函数
//使用格式:
//mem_fun_ref(&类名::函数名)
for_each(v.begin(), v.end(), mem_fun_ref(&Person::show));
//mem_fun_ref 和 mem_fun 的区别?
//存放的是对象,使用mem_fun_ref
//存放的是对象指针,用mem_fun
vector<Person*> v1;
v1.push_back(&p1);
v1.push_back(&p2);
v1.push_back(&p3);
for_each(v1.begin(), v1.end(), mem_fun(&Person::show));
}
int main()
{
test01();
test02();
test03();
test04();
}
char* 转 string:
const char* ch = "abc";
//或者 char ch[] = "abc";
string str1(ch);//调用构造函数
string str2 = ch;
char* ch = "abc";
string str(ch, ch + strlen(ch));
string 转 char*:
string str;
char* ch = const_cast<char*>(str.c_str());
string str;
char* ch = &str[0];
string str1;
string str2(10, 'a');
string str3("abc");
string str4(str3);
string str1;
string str2("abc");
str1 = "abc";
str1 = str2;
str1 = 'a';
str1.assign("abc");
//重载[]操作符
for(int i = 0; i < str1.size(); i++)
{
cout << str1[i] << endl;
}
//at成员函数
for(int i = 0; i < str1.size(); i++)
{
cout << str1.at(i) << endl;
}
//[]和at区别:
//越界时,[]会崩溃;at会抛异常out_of_range
//重载+=操作符
string str1("abc");
str1 += "def";
//append函数
string str2;
str2.append(str1);
//find函数,从前往后查找,返回第一次查找到的位置
string str("abcdefghfg");
int pos = str.find("fg"); //5
//rfind函数,从后往前查找,返回第一次查找到的位置
int rpos = str.rfind("fg");//8
//replace
string str("abcdefg");
str.replace(3,2,"111");//从3位置用111替换2个字符,答案abc111fg
//compare 根据ASCII码比较
// > 时返回1
// < 时返回-1
// == 时返回 0
string str("bbb");
int ret; // a b c ASCII码依次是97 98 99
ret = str.compare("aaa");// 1
ret = str.compare("bbb");// 0
ret = str.compare("ccc");// -1
string str("abcdef");
string subs = str.substr(1,3);//从位置1开始的3个字符,答案bcd
//insert
string str("abcdef");
str.insert(2,"111");//从位置2插入111
str.insert(2,3,'h');//从位置2插入3的字符h
str.erase(3,2);//从位置3开始删除2个字符
vector,动态数组,可以根据元素的数量实现数组长度的动态增长,也是一个单口数组,一般是从数组一端(数组尾部)进行插入和删除,效率很高,如果在中间位置插入,会引起大量数据的移动,效率偏低。
//1.
vector<int> v1;
vector<int> v2 = {
1,2,3.0,4,5,6,7};
vector<int> v3 {
1,2,3.0,4,5,6,7};
//2.
vector<int> v4(v2.begin(), v2.end());//复制区间
vector<int> v5 = v2;
vector<int> v6(v2);//复制构造函数
vector<int> v7(7);//7个缺省值的初始化
vector<int> v8(20,1);//用20个1初始化
//插入
vector<int> v;
v.push_back(1);//尾部增加一个元素
v.insert(v.begin(),2);//开始迭代器增加一个元素
v.insert(v.begin(),5,3);//开始迭代器位置增加5个相同的元素3
//存取元素
vector<int> v;
int front = v.front();//第一个元素
int back = v.back();//最后一个元素
//重载[]操作符
for(int i = 0; i < v.size(); i++)
{
cout << v[i] << endl;
}
//at成员函数
for(int i = 0; i < v.size(); i++)
{
cout << v.at(i) << endl;
}
//[]和at区别:
//越界时,[]会崩溃;at会抛异常out_of_range
//删除
v.erase(v.begin()+2);//删除begin+2位置的元素
v.erase(v.begin()+3, v.end());//删除从begin+3位置到end之间的元素
v.pop_back();//删除最后一个元素
v.clear();//清空
vector<int> v;
int size = v.size();//目前已有的元素个数
int capacity = v.capacity();//可以容纳的元素个数
int ret = v.empty();//容器是否为空
//resize 改变当前使用的容器的大小
//如果比当前容量大,则填充默认值
//否则删除多余的元素
vector<int> v;
v.resize(10);//默认10个0
v.resize(2);//删除后面的8个0
//reserve 改变当前vecotr所分配空间的大小
v.reserve(10);//申请了容量为10的大小的空间
//区别:
//1、
//resize的空间中存在对象,可以直接访问
//reserve的不存在对象,在push_back/insert之前不能访问
//2、
//resize改变size和capacity
//reserve只改变capacity
int vv1, vv2;
int size, capacity;
vv1.resize(20);
size = vv1.size();//20
capacity = vv1.capacity();//20
vv2.reserve(20);
size = vv2.size();//0
capacity = vv2.capacity();//20
//压缩capacity
vector<int> (v).swap(v);
deque是一个双端数组,即本身是一个数组,而且可以从数组头部和尾部进行插入和删除,效率较高,如果从中间位置插入,也会引起大量数据的移动,效率较低。
与vector的不同之处:
//1、
deque<int> d1;
deque<int> d2(d1.begin(), d1.end());
deque<int> d3(10,3);//10个3初始化
deque<int> d4(d2);//拷贝构造
//2、
deque<int> d;
d.assign(d2.begin(), d2.end());
d.assign(10, 3);//10个3赋值
d = d2;//=运算符
d.swap(d2);//与d2的元素交换
deque<int> d;
int size = d.size();
int ret = d.empty();//是否为空
//用法与vector的resize相同
d.resize(10);//10个默认元素指定deque的大小
d.resize(10, 3);//10个3指定deque的大小
deque<int> d;
d.push_back(1);//尾部添加
d.push_front(2);//头部添加
d.insert(d.begin(),2);//开始位置增加一个元素
d.insert(d.begin(),5,3);//开始位置增加5个相同的元素3
d.pop_back();//删除最后一个元素
d.pop_front();//删除第一个元素
//存取元素
deque<int> d;
int front = d.front();//第一个元素
int back = d.back();//最后一个元素
//重载[]操作符
for(int i = 0; i < d.size(); i++)
{
cout << d[i] << endl;
}
//at成员函数
for(int i = 0; i < d.size(); i++)
{
cout << d.at(i) << endl;
}
//[]和at区别:
//越界时,[]会崩溃;at会抛异常out_of_range
list的底层结构是一个双向链表,既然是链表,那么在任意位置插入和删除效率很高,遍历效率很差。同时,由于需要保存前驱和后继节点的关系,相较于数组而言,需要额外的空间。
list<int> list1;//默认构造
list<int> list2(list1.begin(), list1.end());//以list1的begin到end初始化
list<int> list3(10, 3);//10个3初始化
list<int> list4(list2);//拷贝构造
list<int> list1;
list<int> list2;
list2.assign(list1.begin(), list1.end());
list2.assign(10, 3);//10个3赋值
list2 = list1;//重载=操作·操作符
list2.swap(list1);//两个list内的元素交换
//插入
list<int> lisT;
lisT.push_back(1);//在尾部插入元素
lisT.push_front(2);//在头部插入元素
lisT.insert(3,5);//在位置3插入元素5
//存取
int front = lisT.front();//头部第一个元素
int back = lisT.back();//尾部第一个元素
//删除
lisT.pop_back();//删除尾部的第一个元素
lisT.pop_front();//删除头部的第一个元素
lisT.erase(3);//删除位置3的元素
lisT.erase(2,4);//删除位置2到4之间的元素
lisT.remove(5);//删除list中所有的5
list<int> lisT;
int size = lisT.size();//元素个数
int ret = lisT.empty();//是否为空
lisT.resize(10);//重置大小为10
//打印所有的元素
for(list<int>::iterator it = lisT.begin(); it < lisT.end(); it++)
{
cout << *it << " " << endl;
}
list<int> lisT;
lisT.sort();//排序。成员函数,不是算法。默认升序
lisT.reverse();//翻转(逆序)
//如何使list降序排序?
//使用回调函数
bool MyCompare(int v1, int v2)
{
return v1 > v2;
}
lisT.sort(MyCompare);
栈是一种很重要的数据结构,具有“先进后出”的规则,只能在一端进行插入和删除。因为这个规则,栈没有提供迭代器,不能进行元素的遍历和随机访问。如果想要取得最底层的元素,需要从栈顶元素开始依次弹出。
//初始化
stack<int> s1;//默认构造
stack<int> s2(s1);//拷贝构造
//赋值
stack<int> s3;
s3 = s2;//重载等号运算符
stack<int> s;
s.push(1);//压栈(进栈)
s.push(2);
//删除
int top = s.top();//取得栈顶元素
s.pop();//删除(弹出)栈顶元素
stack<int> s;
int size = s.size();//栈内元素的个数
int ret = s.empty();//栈是否为空
//打印栈内所有的元素
while(!s.empty())
{
cout << s.top() << " " << endl;
s.top();
}
queue的规则是“先进先出”,在一端(队尾)进行插入,在另一端(队头)进行删除。队列同样不提供迭代器,不支持元素的遍历和随机访问。
queue<int> q1;//默认构造
queue<int> q2(q1);//拷贝构造
queue<int> q3;
q3 = q2;//重载=运算符
queue<int> q;
q.push(1);
q.push(2);//队尾插入元素
int front = q.front();//返回队头的第一个元素
int back = q.back();//返回队尾的第一个元素
q.pop();//删除队头的第一个元素
queue<int> q;
int size = q.size();//队列元素的个数
int ret = q.empty();//队列是否为空
//打印队列内所有的元素
while(!q.empty())
{
cout << q.front() << " " << endl;
q.pop();
}
set/mulitset的特性是所有元素会根据元素的值进行自动排序,其底层结构是红黑树(RB-tree)。set不允许两个元素有相同的值。不能通过set的迭代器去修改set元素,因为这样操作会打破原有的顺序。multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复。set和multiset的底层实现是一种高效的平衡二叉树,即红黑树(Red-Black Tree)。
set<int> s;//默认构造
mulitset<int> ms;//默认构造
set<int> s2(s);//拷贝构造
set<int> s3;
s3 = s2;//重载=运算符
s3.swap(s1);//交换元素
set<int> s;
s.insert(1);
s.insert(2);
s.erase(2);//删除set中值为2的元素
s.erase(2,4);//删除位置2到4之间的元素
s.erase(s.begin());//删除第一个元素
s.clear();//清空所有元素
set<int> s;
//查找,若找到就返回该元素的迭代器,否则返回s.end()
set<int>::iterator ret = s.find(2);
//返回第一个大于等于2的迭代器
set<int>::iterator it1 = s.lower_bound(2);
//返回第一个大于2的迭代器
set<int>::iterator it2 = s.upper_bound(2);
//返回lower_bound和upper_bound的迭代器
pair<set<int>::iterator, set<int>::iterator> mypair = s.equal_range(2);
//通过mypair.first和mypair.second来访问pair中的两个迭代器
//1、基本数据类型
class MyCompare
{
public:
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
set<int, MyCompare> s; //升序排序
//2、自定义数据类型
class Person
{
public:
Person(int id, int age):id(id), age()age{
}
public:
int id;
int age;
};
class MyCompare02
{
public:
bool operator()(Person p1, Person p2)
{
return p1.id > p2.id;
}
};
set<Person, MyCompare02> s; //按照id升序排序自定义数据类型
Person p1(10,20), p2(30,40);
s.insert(p1);
s.insert(p2);
//!!!!!!!注意!!!!!!!!!!
Person p3(10,40);
s.find(p3);//可以查找到,查找的结果是p1的迭代器
//原因:由于person是根据id排序的,因此查找的时候也会跟id来找。
//
set<int> s;
int size = s.size();
int ret = s.empty();//是否为空
//打印所有元素
for(set<int>::iterator it = s.begin(); s < it.end(); it++)
{
cout << *it << " " << endl;
}
C++中map提供的是一种键值对容器,里面的数据都是成对出现的,如下图:每一对中的第一个值称之为关键字(key),每个关键字只能在map中出现一次;第二个称之为该关键字的对应值。
Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。相对于set区别,map具有键值和实值。map内部自建一颗红黑树,这颗树根据key对数据进行自动排序,所以在map内部所有的数据都是有序的。
map与multimap的不同之处在于,map的键值key不可重复,而multimap可以,也正是由于这种区别,map支持[ ]运算符,multimap不支持[ ]运算符。在用法上没什么区别。
map<int, int> m1;//默认构造
mulitmap<int, int> mm;//默认构造
map<int, int> m2(m1);//拷贝构造
map<int, int> m3;
m3 = m2;//重载=运算符
m3.swap(m1);//交换元素
map<int, int> m;
//1、第一种方式
pair<map<int, int>::iterator, bool> ret = m.insert(pair<int, int>(10, 20));
//insert返回的是pair<iterator, bool>,可以根据第二个参数判断是否插入成功--ret.second
//2、第二种方式
m.insert(make_pair(30, 40));
//3、第三种方式
m.insert(pair<int, int>::value_type(50, 60));
//4、第四三种方式
m[70] = 80;
//!!!!!!注意!!!!!!
//前三种插入方式没有区别
//第四种插入方式
//如果key不存在,则会创建一个新的pair插入
//如果key存在,则会修改该key对应的实值
//如果通过[]去访问一个不存在的key,
//那么map会将这个key插入到map中,
//并且给对应的实值一个默认值
class MyKey()
{
public:
MyKey(int index, int id):index(index),id(id){
}
public:
int index;
int id;
};
class MyCompare()
{
public:
bool operator()(MyKey key1, MyKey key2)
{
return key1.index > key2.index;
}
};
map<MyKey, int, MyCompare> m;
m.insert(make_pair(MyKey(1,2),10));
m.insert(make_pair(MyKey(2,4),20));
map<int, int> m;
//根据键值查找,若找到就返回该元素的迭代器,否则返回m.end()
pair<map<int, int>::iterator,map<int, int>::iterator> ret = s.find(2);
//返回第一个大于等于2的迭代器
map<int, int>::iterator it1 = s.lower_bound(2);
//返回第一个大于2的迭代器
map<int, int>::iterator it2 = s.upper_bound(2);
//返回lower_bound和upper_bound的迭代器
pair<map<int, int>::iterator, map<int, int>::iterator> mypair = s.equal_range(2);
容器深拷贝与浅拷贝
class Person()
{
public:
Person(char* name, int age)
{
this->name = new char[strlen(name)+1];
strcpy(this->name, name);
this->age = age;
}
//需要添加拷贝构造函数和重载=操作符,否则会是浅拷贝,导致程序崩溃
Person(const Person& p)
{
this->name = new char[strlen(p.name)+1];
strcpy(this->name, p.name);
this->age = p.age;
}
Person& operator=(const Person& p)
{
if(this->name != NULL)
{
delete[] this->name;
}
this->name = new char[strlen(p.name)+1];
strcpy(this->name, p.name);
this->age = p.age;
}
~Person()
{
if(this->name != NULL)
{
delete[] this->name;
}
}
public:
char* name;
int age;
};
Person p("aaa",20);
vector<Person> v;
v.push_back(p);
STL容器所提供的都是值寓意,而非引用寓意,也就是说当我们给容器中插入元素时,容器内不实现了拷贝动作,将要插入的元素拷贝一份再放入到容器中,而不是将原始原始直接放进容器中,也就是说我们所提供的元素必须能被拷贝。
vector | deque | list | set | multiset | map | multimap | |
---|---|---|---|---|---|---|---|
典型内存结构 | 单端数组 | 双端数组 | 双向链表 | 二叉树 | 二叉树 | 二叉树 | 二叉树 |
随机存取 | 是 | 是 | 否 | 否 | 否 | 对key而言是:是 | 否 |
元素搜素速度 | 慢 | 慢 | 非常慢 | 快 | 快 | 对key而言:快 | 对key而言:快 |
元素安插移除 | 尾部 | 头尾两端 | 任意位置 | - | - | - | - |
vector和deque的比较
文章浏览阅读3.9k次。https://blog.csdn.net/xiaodingqq/article/details/87690563遇到的错误:_rotmaster报错是个无效的robotmaster
文章浏览阅读2.4k次,点赞2次,收藏9次。正交矩阵是实数特殊化的酉矩阵,因此总是正规矩阵。尽管我们在这里只考虑实数矩阵,这个定义可用于其元素来自任何域的矩阵。正交矩阵毕竟是从内积自然引出的,对于复数的矩阵这导致了归一要求。定义 定义 1 如果:AA'=E(E为单位矩阵,A'表示“矩阵A的转置矩阵”。)或A′A=E,则n阶实矩阵 A称为正交矩阵, 若A为正交阵,则满足以下条件: ..._正交矩阵
文章浏览阅读4.2k次。如下图所示,左边无用白块太多,而且线基本到不了左边那一块,所以想弄个掩模把左边弄成纯黑色。下图是打算使用的掩模下图是原来的程序,结果报错,错误如标题所示。# 掩模创建def roi_mask(img,corner1_points,corner2_points): mask = np.zeros_like(img) cv.fillPoly(mask,corne..._(-215:assertion failed) p.checkvector(2, cv_32s) >= 0 in function 'cv::polyl
文章浏览阅读1k次。智东西7月11日消息,昨日,MLPerf基准联盟公布了最新一轮的基准测试数据,结果显示,英伟达和谷歌云刷新了人工智能训练时间的记录。MLPerf是一项用于测试ML(Machine Learning)硬件、软件以及服务的训练和推理性能的公开基准。它能帮助人工智能研究人员采用通用标准来衡量用于训练人工智能的硬件、软件的最佳性能和速度。目前,MLPerf基准测试正迅速成为测量机器学习性能的行业标..._tpu 芯片
文章浏览阅读7.8k次,点赞9次,收藏66次。JSP隐式对象:(1) out 用于页面输出 (2) request 得到用户请求信息 (3) response 服务器向客户端回应信息 (4) config 服务器配置,可以取得初始化参数 (5) session 用来保存用户的信息 (6) application 所有用户的共享信息 (7) page 指当前页面转换后的Servlet类的实例 (8) pageContext JSP的页面容器 (9) exception 表示JSP页面所发生的异常,在错误页中才起作用。......_jsp隐式对象out可以通过response.getwriter()方式获取,然后再通过println()或者wr
文章浏览阅读603次。window10下载地址_window10下载
文章浏览阅读3.3k次,点赞2次,收藏4次。seata安装版本是1.5.2,版本不同,安装流程也可能不同,这里的版本需要保持一致执行sql创建数据表使用脚本添加配置到nacos配置中心修改文件,分别修改store、config、registry相关配置。启动服务,成功登陆seata控制台。查看nacos控制台,服务列表新增seata服务。_apm-skywalking not enabled
文章浏览阅读340次。本例使用的时python2.7环境,python3的操作应该也是差不多的。需要用到smtplib和email两个包。发送文本类型的邮件下面看个发送文本邮件的例子(使用网易163的SMTP):# -*- coding: UTF-8 -*-import smtplibfrom email.mime.text import MIMETextfrom email.header import..._smtp_obj.quit()
文章浏览阅读6.4w次,点赞11次,收藏43次。Linux下mysql默认区分大小写Windows下mysql默认不区分大小写查看是否区分大小写show variables like 'lower%'lower_case_table_names参数详解: lower_case_table_names = 0 其中 0:区分大小写,1:不区分大小写 MySQL在Linux下数据库名、表名、列名、别名大小写规则是这样的: 1、数据库名与表名是..._dbms: mysql (版本 8.0.32) 区分大小写: 普通形式=lower,分隔形式=lower 驱动程序
文章浏览阅读765次。matplotlib基本函数整理_plt模块
文章浏览阅读1.3k次。1:设置该选项: public void setSoLinger(boolean on, int seconds) throws SocketException; 读取该选项:public int getSoLinger() throws SocketException SO_LINGER选项用来控制Socket关闭时的行为,默认情况下,执行Socket的close_socket.setlinger
文章浏览阅读5.7k次。一、参考https://www.cnblogs.com/roland-sky/p/12916645.htmlvue.config.js 配置devServer: { // 如果改动node_modules内的代码, 不会触发热重载, 则取消下面的注释 // watchOptions: { // ignored: [] // }, proxy: { '^/api/': { target: 'http://localhost:8060', cha_config.js中配置proxy