目录
1.关键字作用
1.1基类里面常用关键字
1.1.1 const修饰
一、const修饰成员函数
1.成员函数后加const称这个函数为常函数;
2.常函数不可以修改成员变量;
3.成员变量前加mutable后,即可在常函数中修改。
二、常对象
1.声明对象前加const的对象称为常对象;
2.常对象只能调用常函数。
参考C++之const修饰成员函数_const修饰函数_软硬兼施的程序员的博客-CSDN博客
示例代码:
int width() const { return metric(PdmWidth); }
1.1.2 virtual修饰作用
虚函数是指一个类中你希望重载的成员函数 ,当你用一个 基类指针或引用 指向一个继承类对象的时候,调用一个虚函数时, 实际调用的是继承类的版本。 ——摘自MSDN
示例代码:
virtual int devType() const;
1.1.3 static修饰作用
- (1)静态成员函数中不能调用非静态成员。
- (2)非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象产生之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。
- (3)静态成员变量使用前必须先初始化(如 int MyClass::m_nNumber = 0;),否则会在 linker 时出错。
一般总结:在类中,static 可以用来修饰静态数据成员和静态成员方法。
静态数据成员
- (1)静态数据成员可以实现多个对象之间的数据共享,它是类的所有对象的共享成员,它在内存中只占一份空间,如果改变它的值,则各对象中这个数据成员的值都被改变。
- (2)静态数据成员是在程序开始运行时被分配空间,到程序结束之后才释放,只要类中指定了静态数据成员,即使不定义对象,也会为静态数据成员分配空间。
- (3)静态数据成员可以被初始化,但是只能在类体外进行初始化,若未对静态数据成员赋初值,则编译器会自动为其初始化为 0。
- (4)静态数据成员既可以通过对象名引用,也可以通过类名引用。
静态成员函数
- (1)静态成员函数和静态数据成员一样,他们都属于类的静态成员,而不是对象成员。
- (2)非静态成员函数有 this 指针,而静态成员函数没有 this 指针。
- (3)静态成员函数主要用来方位静态数据成员而不能访问非静态成员。
示例代码:
static inline qreal devicePixelRatioFScale() { return 0x10000; }
1.1.4 friend修饰作用
C++中的友元机制允许类的非公有成员被一个类或者函数访问,友元按类型分为三种:普通非类成员函数作为友元,类的成员函数作为友元,类作为友元。友元包括友元的声明以及友元的定义。友元的声明默认为了extern,就是说友元类或者友元函数的作用域已经扩展到了包含该类定义的作用域,所以即便我们在类的内部定义友元函数也是没有关系的。
示例代码:
friend class QPainter;
1.1.5inline修饰作用
引入 inline 关键字的原因
在 c/c++ 中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,表示为内联函数。
栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间。
在系统下,栈空间是有限的,假如频繁大量的使用就会造成因栈空间不足而导致程序出错的问题,如,函数的死循环递归调用的最终结果就是导致栈内存空间枯竭。
实例:
#include <stdio.h> inline const char *num_check(int v) { return (v % 2 > 0) ? "奇" : "偶"; } int main(void) { int i; for (i = 0; i < 100; i++) printf("%02d %s\n", i, num_check(i)); return 0; }
上面的例子就是标准的内联函数的用法,使用 inline 修饰带来的好处我们表面看不出来,其实,在内部的工作就是在每个 for 循环的内部任何调用 dbtest(i) 的地方都换成了 (i%2>0)?"奇":"偶",这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。
1.1.6final修饰作用
1.禁用继承
C++11中允许将类标记为final,方法时直接在类名称后面使用关键字final,如此,意味着继承该类会导致编译错误。
实例如下:
class Super final
{
//......
};
2.禁用重写
C++中还允许将方法标记为fianal,这意味着无法再子类中重写该方法。这时final关键字至于方法参数列表后面,如下
class Super
{
public:
Supe();
virtual void SomeMethod() final;
};
1.1.7= delete修饰作用
C++11中,当我们定义一个类的成员函数时,如果后面使用"=delete"去修饰,那么就表示这个函数被定义为deleted,也就意味着这个成员函数不能再被调用,否则就会出错。
#include <cstdio>
class TestClass
{
public:
int func(int data)=delete;
};
int main(void)
{
TestClass obj;
obj.func(100);
return 0;
}
1.2 派生类常用关键字
1.2.1 explicit修饰作用
首先, C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式).
用explicit修饰可以防止默认的隐式转换。
参考:C++中的explicit详解_c++ explicit_杨 戬的博客-CSDN博客
示例代码:
explicit QMainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
1.2.2 template 修饰作用
一、函数模板
template< class 形参名,class 形参名,......> 返回类型 函数名(参数列表) { 函数体 }
举个例子:template <class T> void swap(T& a,T& b){}
当调用这样的模板函数时,类型T就会被调用时的类型所代替。如果swap(a, b),a,b都是int类型,那么模板函数swap中的形参T就会被int所代替,模板函数就会变成swap(int &a,int &b)。而当swap(a,b),a,b都是double类型,那么模板函数swap中的形参T就会被double所代替,模板函数就会变成swap(double &a,double &b),这样如果我们的程序中交换变量的值就不再受限于类型了。
template< class 形参名,class 形参名,......> class 类名 {...};
举个例子:template <class T> class A { public: T a; T b; T hy(T c, T &d); };
在类A中声明了两个类型为T的成员变量a和b,还声明了一个返回类型为T带两个参数类型为T的函数hy。
示例代码:
template <> inline QWidget *qobject_cast<QWidget*>(QObject *o)
{
if (!o || !o->isWidgetType()) return nullptr;
return static_cast<QWidget*>(o);
}
1.2.3 noexcept修饰作用
noexcept 是一个 C++11 引入的关键字,用于表示一个函数或表达式在执行期间是否会抛出异常。它可以作为函数的一部分声明,也可以作为表达式的一部分使用。
-
提高代码效率:如果一个函数使用了 noexcept声明,编译器会认为这个函数不会抛出异常,从而可以对这个函数进行一些优化,例如避免额外的堆栈操作和异常处理代码等,从而提高代码效率。
-
帮助程序员调试:如果一个函数没有使用 noexcept声明,并且在函数内部抛出了异常,这个异常会在函数的调用栈上一路传递直到被捕获,如果捕获不到,程序就会崩溃。而如果使用了 noexcept声明,那么一旦函数内部抛出了异常,程序就会直接调用 std::terminate()函数终止程序,这可以帮助程序员快速发现和调试程序中的异常问题。
-
帮助编写高质量代码:使用 noexcept声明可以帮助编写高质量的代码,因为它可以明确表示函数是否会抛出异常,从而让函数的调用者更容易正确地处理异常情况。
参考:noexcept语法解析_LiuZuqiang_3027的博客-CSDN博客
示例代码:
inline QByteArray() noexcept;
1.2.4 operator修饰作用
operator 是C++的一个关键字,它和运算符(如=)一起使用,表示一个运算符重载函数,在理解时可将operator和运算符(如operator=)视为一个函数名。
使用operator重载运算符,是C++扩展运算符功能的方法。使用operator扩展运算符功能的原因如下:
使重载后的运算符的使用方法与重载前一致
扩展运算符的功能只能通过函数的方式实现(实际上,C++中各种“功能”都是由函数实现的)
示例代码:
Q_REQUIRED_RESULT inline QByteRef operator[](uint i);
1.2.5 override修饰作用
如果派生类在虚函数声明时使用了override描述符,那么该函数必须重载其基类中的同名函数,否则代码将无法通过编译。
参考:C++ override 关键字用法_xiaoheibaqi的博客-CSDN博客
示例代码:
bool open(OpenMode mode) override;
2.常用语法
2.1 引用&用法
只需将函数声明为引用即可,不用传参时按引用传。
示例代码:
#include <iostream>
void plus(int &n){
n = n + 1;
}
void plus1(int n){
n = n+1;
}
int main(int argc, const char * argv[]) {
// insert code here...
int a = 10, b = 10;
plus(a);
plus1(b);
printf("a = %d \nb = %d \n",a,b);
}
最后输出: a = 11
b = 10
3.C++常用标准模板库
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<iostream>
#include<algorithm>
#include<iterator>
#include<vector>
#include<list>
#include<queue>
#include<stack>
#include<set>
#include<bitset>
#include<map>
using namespace std;
3.1vector
3.1vector容器的特性
C语言中,我们常常为数组开多大而烦恼,这时vector能很好的解决数组越界等情况。
vector即向量,我们称他为“不定长数组”比较好,它的长度会根据需要而自动变化,另外vector还可以用来以邻接链表的方式储存图,另外Vector在使用时需要声明#include<vector>
以及using namespace std;
vector<typename> name;
- 定义Vector数组的方法
vector<typename> arrayname[arraysize];
3.2vector容器内元素的访问
vector一般有两种访问方式:
- 通过下标访问:
与普通数组访问方式相同! - 通过迭代器访问:
可以理解为通过指针访问,其定义为:vector<int>::iterator it;
这样我们便定义好了一个迭代器(iterator)it,并且可以通过*it来访问vector里面的元素。举个例子:
vector<int>vi;
for(vector<int>::iterator it = vi.begin();it != vi.end;it++)
{
printf("%d",*it);
}//vi是已经定义好的一个数组
3.3vector常用函数
begin();
获取vector首元素地址。例:for(vector<int>::iterator it = vi.begin();it != vi.end;it++)
end();
获取vector末元素的地址。例:同上
注:vector迭代器不支持it < vi.end()
的写法,因此只能用it != vi.end()
push_back(x)
再vector后面添加一个元素x 例:vi.push_back(x);
pop.back();
删除vector的尾元素。 例:vi.pop.back();
size();
获取vector中元素个数。 例:vi.size();
clear();
清除vector中所有的元素。例:vi.clear();
insert(it,x);
向vector的任意迭代器it处插入一个元素x。例:vi.insert(vi.begin()+2,-1);//再数组vi第二个元素后插入-1
erase();
erase()有两种用法:1.erase(it);
删除迭代器为it处的元素
2.erase(first,last)
删除[first,last)区间里的元素。
3.4vector初始化的4种方式
void ceshi(vector<int> v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}
}
//四种方式 1
vector<int > v;
int arr[] = { 1,2,3,4,5,6 };
//2 最常用
vector<int> v1(arr,arr+sizeof(arr)/sizeof(int));
//3
vector<int> v2(v1.begin(), v1.end());
//4
vector<int> v3(v2);
ceshi(v1);
ceshi(v2);
ceshi(v3);
其他详细介绍参考:[STL]Vertor基本用法解释+代码实例_Windalove的博客-CSDN博客
3.2string
1、string(const char *s)
:将 string 对象初始化为 s 指向的字符串
string str("hello");
2、string(size_type n,char c)
:创建一个包含 n 个元素的 string 对象,其中每个元素都被初始化为字符 c
string str(10, 'a');
3、string(const string &str)
:将一个 string 对象初始化为 string 对象 str(复制构造函数)
string str("abcde");
string str2(str);
4、string()
:创建一个默认的 string 对象,长度为 0(默认构造函数)
string str;
5、使用C语言风格字符串处理string对象
string str = "hello!";
6、获取string对象的长度,C语言中使用strlen()来获取字符串长度,C++中使用str.size()
或str.length()
.
string str("hello!");
int len1 = str.size();
int len2 = str.length();
7、将一个 string 对象赋值给另一个 string 对象
string str("hello!");
string str2;
str2 = str;
8、string 对象的拼接
C 语言中使用 strcat、strncat 函数来进行字符串拼接操作,C++中可以采用以下方式:
string str1("hello");
string str2("world");
string str3 = str1 + str2;
9、使用 += 来在一个 string 对象后面附加一个 string 对象、字符以及 C 风格的字符串
string str("hello");
string str2("world");
str += str2;
str += 'a';
str += "abcd";
10、string.append() 函数,在string对象后添加一个string对象或c风格字符串。
string str("hello");
string str2("world");
str.append(str2);
str.append("abcd");
11、string.push_back() 函数来在一个 string 对象后面附加一个字符
string str("hello");
char ch = 'a';
str.push_back(ch);
12、对于string对象的比较,可以直接使用关系运算符。
string str1("abcd");
string str2("abcd");
if(str1 == str2)
break;
13、string对象的比较也可以使用string.compare() 方法
int compare(const string&str) const;
int compare(size_t pos,size_t len,const string&str)const;
int compare(size_t pos,size_t len,const string&str, size_t subpos,size_t sublen)const;
int compare(const char * s)const;
int compare(size_t pos,size_t len,const char * s)const;
int compare(size_t pos,size_t len,const char * s,size_t n)const;
// example
string str1("hello world");
string str2("hello boy");
str1.compare(6, 3, str2, 6, 3);
14、使用 string.substr() 函数来获取子串
string str("hello");
string str2 = str.substr(3,2)
15、访问 string 字符串的元素
string str("hello");
cout << str[2] << endl;
cout << str.at(2) << endl;
16、使用 string.find()
方法查找字符
// 从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找子字符串 str。
// 如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos:
// string 类将 npos 定义为保证大于任何有效下标的值。
size_type find (const string& str, size_type pos = 0) const;
size_type find (const char *s, size_type pos = 0) const;
size_type find (const char *s, size_type pos, size_type n);
size_type find (char ch, size_type pos = 0) const;
17、string.rfind()
与 string.find() 方法类似,只是查找顺序不一样, string.rfind() 是从指定位置 pos (默认为字符串末尾)开始向前查找,直到字符串的首部,并返回第一次查找到匹配项时匹配项首字符的索引。换句话说,就是查找子字符串或字符最后一次出现的位置。
18、string.find_first_of()
方法在字符串中从指定位置开始向后(默认为索引 0 处)查找参数中任何一个字符首次出现的位置
string str("hello world");
int pos = str.find_first_of("abcde");
int pos = str.find_first_of("abcde", 1); // 第二个参数为位置
19、string.find_last_of()
方法在字符串中查找参数中任何一个字符最后一次出现的位置
20、string.find_first_not_of()
方法在字符串中查找第一个不包含在参数中的字符
21、string.find_last_not_of()
方法在字符串中查找最后一个不包含在参数中的字符
22、使用 string.insert()
进行插入操作
string& insert(size_t pos,const string&str);
// 在位置 pos 处插入字符串 str
string& insert(size_t pos,const string&str,size_t subpos,size_t sublen);
// 在位置 pos 处插入字符串 str 的从位置 subpos 处开始的 sublen 个字符
string& insert(size_t pos,const char * s);
// 在位置 pos 处插入字符串 s
string& insert(size_t pos,const char * s,size_t n);
// 在位置 pos 处插入字符串 s 的前 n 个字符
string& insert(size_t pos,size_t n,char c);
// 在位置 pos 处插入 n 个字符 c
iterator insert (const_iterator p, size_t n, char c);
// 在 p 处插入 n 个字符 c,并返回插入后迭代器的位置
iterator insert (const_iterator p, char c);
// 在 p 处插入字符 c,并返回插入后迭代器的位置
23、使用 string.erase() 进行元素删除操作
string& erase (size_t pos = 0, size_t len = npos); // 删除从 pos 处开始的 n 个字符
iterator erase (const_iterator p); // 删除 p 处的一个字符,并返回删除后迭代器的位置
iterator erase (const_iterator first, const_iterator last); // 删除从 first 到last 之间的字符,并返回删除后迭代器的位置
24、使用 getline() 函数来获取 string 输入
string str;
getline(cin, str);
25、使用 string.empty() 函数判断字符串是否为空
26、使用 string.swap() 函数交换两个字符串
string str1 = "hello";
string str2 = "HELLO";
str1.swap(str2);
27、string.back()
获取或修改字符串最后一个字符
string str("abcd");
char b = str.back();
str.back() = 'e';
28、string.front()
获取或修改字符串第一个字符
29、string.pop_back()
删除字符串最后一个元素
3.3queue和priority_queue
3.3.1queue
queue就是队列,在STL中是实现了一个先进先出的容器,要使用queue,需要在加上queue这个头文件。
queue的定义,queue<typename> q;其中typename可以为任何类型或容器。
queue的访问,由于队列是一种先进先出的限制性数据结构,因此在STL中只能通过front()来访问队首元素,或是通过back()来访问队尾元素。
queue<`int`> q ;
for(int i=1;i<5;i++){
q.push(i) ;
}
cout << q.front() << endl ;
cout << q.back() << endl ;
输出结果:1
4
Queue常用函数
(1) push(),push(x)将x入队,时间复杂度O(1)
(2) front(),访问队首元素,back()访问队尾元素,时间复杂度O(1)。
(3) pop(),令队首元素出队,时间复杂度O(1)。
queue<int> q ;
for(int i=1;i<5;i++){
q.push(i) ;
}
q.pop() ;
cout << q.front() << endl ;
cout << q.back() << endl ;
输出结果:2
4
(4) empty(),判断队列是否为空,如果是空则返回true,否则返回false。
(5) size(),返回queue内元素的个数,时间复杂度为O(1)。
queue<int> q ;
for(int i=1;i<5;i++){
q.push(i) ;
}
if(!q.empty()){
cout << q.size() ;
}
输出结果:4
Queue的常见用途:
当需要实现广度优先搜索时,可以不用自己手工实现一个队列。在使用front()和pop()函数前,必须使用empty()判断队列是否为空,否则可能因为队空而出现错误。
3.3.2priority_queue
priority_queue又称优先队列,其底层是用堆来进行实现的。在优先队列中,队首的元素一定是当前队列中优先级最高的那一个。C++中的堆默认是大跟堆。
priority_queue的定义,priority_queue<typename> q,typename可以为任意类型的元素。要使用优先队列,应先添加头文件#include[HTML_REMOVED]。
Priority_queue只能通过top()函数来访问队首元素(堆顶元素),也就是优先级最高的元素。
priority_queue<int> q ;
q.push(3) ;
q.push(1) ;
q.push(5) ;
cout << q.top() << endl ;
输出结果:5
Priority_queue常用函数
(1) push(x),时间复杂度O(logN),N是堆中元素的个数。
(2) top(),top()可以获得队首元素,时间复杂度O(1)
(3) pop(),令堆顶元素出队,时间复杂度O(logN),其中N是堆中的元素个数。
priority_queue<int> q ;
q.push(3) ;
q.push(1) ;
q.push(5) ;
cout << q.top() << endl ;
q.pop() ;
cout << q.top() << endl ;
输出结果:5
3
(4) empty(),判断队列是否为空,为空返回true,否则返回false。
(5) size(),返回优先队列中元素的个数,时间复杂度O(1)
priority_queue<int> q ;
q.push(3) ;
q.push(1) ;
q.push(5) ;
if(!q.empty()){
cout << q.size() << endl ;
}
输出结果:3
3.4map
map翻译成映射,map可以将任何基本类型(包括STL容器)映射到任何基本类。(包括STL容器)。如要使用map,需要添加map头文件,并在头文件底下加上“using namespace std”,这样就可以在代码中使用map了。
map的定义,map[HTML_REMOVED] mp;map和其他STL容器的定义上有点不同,因为map需要确定映射前类型(键key)和映射后类型(值value),map存储的数据类型是一对K-V结构的数据。如果map是字符串到整型的映射,必须使用string而不能使用char数组。
map的访问,map一般有两种访问方式,通过“下标”访问或者通过迭代器访问。
(1) 通过“下标”访问,和普通数组的访问方式一样。比如,定义了一个map[HTML_REMOVED] mp;的map,可以使用mp[“hello”] = 8的方式向map中添加数据,用mp[“hello”]访问map中键为“hello”的值。map中的键是唯一的,可以观察下面代码的输出。
unordered_map<string,int> um ;
um["hello"] = 8 ;
um["hello"] = 100 ;
cout << um["hello"] << endl ;
输出:100
(2) 通过迭代器访问,与其他STL迭代器有点不同,由于map的数据类型是K-V结构,因此迭代器包含了这两方面的数据。map迭代器的定义方式为map[HTML_REMOVED]::iterator it;可以通过it->first来访问键,it->second来访问值。观察下面的代码,
map<string,int> mp ;
mp["hello"] = 8 ;
mp["hello"] = 100 ;
mp["aloha"] = 666 ;
mp["good"] = 777 ;
for(map<string,int>::iterator it=mp.begin();it!=mp.end();it++){
cout << it->first << ' ' << it->second << endl ;
}
输出结果:aloha 666
good 777
hello 100
观察输出结果,很有意思的是map按照键值从小到大排序了,如果是字符串,则按照字典序排序。map是采用红黑树来实现的。
map的常用函数:
(1) find(key),返回键为key的映射的迭代器,时间复杂度为O(logN),N为map中映射的个数。
map<string,int> mp ;
mp["hello"] = 8 ;
mp["hello"] = 100 ;
mp["aloha"] = 666 ;
mp["good"] = 777 ;
auto it = mp.find("good") ;
cout << it->first << ' ' << it->second << endl ;
输出结果:good 777
(2) erase(),erase()有两种用法:删除单个元素和删除一个区间内的元素。
a. 删除单个元素,删除单个元素也有两种方法
mp.erase(it),it为需要删除的元素的迭代器,时间复杂度O(1)。
map<string,int> mp ;
mp["hello"] = 8 ;
mp["hello"] = 100 ;
mp["aloha"] = 666 ;
mp["good"] = 777 ;
mp.erase(mp.find("good"));
for(auto ele : mp){
cout << ele.first << ' ' << ele.second << endl ;
}
输出结果:aloha 666
hello 100
mp.erase(key),key为欲删除的映射的键。时间复杂度O(logN)。N为map中元素的个数。
map<string,int> mp ;
mp["hello"] = 8 ;
mp["hello"] = 100 ;
mp["aloha"] = 666 ;
mp["good"] = 777 ;
mp.erase("good");
for(auto ele : mp){
cout << ele.first << ' ' << ele.second << endl ;
}
输出结果:aloha 666
hello 100
b. 删除一个区间的元素,这里只能用迭代器删除,erase(st,ed),表示删除[st,ed)区间内的元素。
map<string,int> mp ;
mp["hello"] = 8 ;
mp["hello"] = 100 ;
mp["aloha"] = 666 ;
mp["good"] = 777 ;
mp.erase(mp.find("good"),mp.find("hello"));
for(auto ele : mp){
cout << ele.first << ' ' << ele.second << endl ;
}
输出结果:aloha 666
hello 100
注意,st的迭代器位置必须在ed之前。
map<string,int> mp ;
mp["hello"] = 8 ;
mp["hello"] = 100 ;
mp["aloha"] = 666 ;
mp["good"] = 777 ;
mp.erase(mp.find("good"),mp.find("good"));
for(auto ele : mp){
cout << ele.first << ' ' << ele.second << endl ;
}
输出结果:aloha 666
good 777
hello 100
其实是什么也没有删除。
(3) size(),用来获得map中映射的对数,时间复杂度O(1)。
map<string,int> mp ;
mp["hello"] = 8 ;
mp["hello"] = 100 ;
mp["aloha"] = 666 ;
mp["good"] = 777 ;
cout << mp.size() << endl ;
输出结果:3
(4) clear(),用来清空map中所有元素,复杂度为O(N),其中N为map中元素的个数。
map<string,int> mp ;
mp["hello"] = 8 ;
mp["hello"] = 100 ;
mp["aloha"] = 666 ;
mp["good"] = 777 ;
mp.clear() ;
cout << mp.size() << endl ;
输出结果:0
map的常见用途:
(1) 需要建立字符(或字符串)与整数之间映射的题目,使用map可以减少代码量。
(2) 判断大整数或者其他类型数据是否存在的题目,可以把map当成bool数组用。
(3) 字符串和字符串之间的映射。
补充:map和键和值都是唯一的,而如果一个键需要对应多个值,就只能使用multimap。另外,C++11标准中还增加了unordered_map,以散列代替map内部的红黑树实现,使其可以用来处理映射而不需要按key排序的需求,速度比map快很多。
3.5set
(一)set:翻译为集合,是一个内部自动有序且不含重复元素的容器。
作用:自动去重并按升序排序
#include<set>
using namespace std;
set<typename> name;
set<typename> Arrayname[arraySize];
set<typename>::iterator it;//定义迭代器it
由于除开vector和string之外的STL容器都不支持*(it+i)的访问方式,因此只能按如下方式枚举:
#include<cstdio>
#include<set>
using namespace std;
int main(){
set<int> st;
st.insert(3);
st.insert(5);
st.insert(2);
st.insert(3);
for(set<int>::iterator it = st.begin(); it != st.emd(); it++){
printf("%d",*it);//输出结果:2 3 5
}
return 0;
}
函数 | 功能 |
---|---|
begin() | 首元素地址 |
end() | 尾元素地址的下一个地址(美国人思维比较习惯左闭右开) |
size() | 元素个数 |
clear() | 清空元素 |
insert(x) | 插入元素 |
find(x) | 查找元素,返回对应元素的迭代器(指针) |
erase(it) | 删除指定位置元素,可结合find函数使用。st.erase(st.find(x)); |
erase(x) | 删除元素x,等价于st.erase(st.find(x)); |
erase(first,last) | 删除 [ first , last ) 内的所有元素 |
3.6stack
(一)stack:翻译为栈,后进先出的容器。
用来模拟实现一些递归,防止程序对栈内存的限制而导致程序运行出错。
#include<stack>
using namespace std;
stack<typename> name;
只能通过top()来访问栈顶元素
函数 | 功能 |
---|---|
size() | 元素个数 |
empty() | 检测是否为空,返回bool |
push(x) | 入栈 |
top() | 获得栈顶元素 |
pop() | 弹出栈顶元素 |
3.7pair
(一)pair:实际上可以看作一个内部有两个元素的结构体
常见用途一:代替二元结构体,节省编码时间
常见用途二:作为map的键值对来进行插入
#include<string>
#include<map>
int main(){
map<string,int> mp;
mp.insert(make_pair("hehe",5));
mp.insert(pair<string,int>("hehe",5));
for(map<string,int>::iterator it = mp.begin(); it != mp.end(); it++){
printf("%c %d\n",it->first,it->second);
}
}
map内部实现涉及pair,因此添加map头文件时会自动添加utility头文件
#include<map>
//或 #include<utility>
using namespace std;
//定义
pair<typename1,typename2> name;
//定义并初始化
pair<string,int> p("haha",5);
//临时变量(只用一次的)
pair<string,int>("haha",5)
或
make_pair("haha",5)
pair中只有两个元素,分别是first和second,只需要按正常结构体的方式去访问即可。
函数 | 功能 |
---|---|
比较运算符 | 比较规则是先以first的大小作为标准,相等时才去判别second的大小 |
3.8algorithm
函数 | 功能 |
---|---|
max(x,y) | 最大值 ( int和double均可) |
max(x,max(y,z)) | 三个数的最大值 |
min(x,y) | 最小值 |
abs(int x) | 绝对值( Note:浮点型的绝对值请用math里的fabs) |
swap(x,y) | 交换 |
reverse(it,it2) | 将数组指针或容器迭代器在[it,it2)范围内的元素反转 |
next_permutation(it,it2) | 给出一个序列在全排列中的下一个序列 |
fill(it,it2,value) | 把数组或容器某区间赋为某个相同的值 |
sort(it,it2) | 排序 |
sort(it,it2,cmp) | 排序 |
lower_bound(it,it2,val) | 寻找数组或容器的[it,it2)范围内第一个值大于等于val的元素的位置,返回指针或迭代器,如果不存在,则返回可插入该元素的指针或迭代器 |
upper_bound(it,it2,val) | 寻找数组或容器的[it,it2)范围内第一个值大于val的元素的位置,返回指针或迭代器,如果不存在,则返回可插入该元素的指针或迭代器 |
count | 统计出现的次数 |
algorithm头文件定义了一个count的函数,其功能类似于find。这个函数使用一对迭代器和一个值做参数,返回这个值出现次数的统计结果。
-
cout << count(v.begin(), v.end(), 1) << endl;
4.C++的23种设计模式
参考
C++设计模式(全23种)_momohola的博客-CSDN博客
一、创建型模式
Factory 模式(工厂模式) //将类的创建放到factory里面统一管理
AbstactFactory 模式(抽象工厂模式)
Singleton 模式( 单例模式)
Builder 模式(建造者模式)
Prototype 模式(原型模式)
二、结构型模式
Bridge 模式(桥接模式)
Adapter 模式(适配器模式)
Decorator 模式(装饰器模式)
Composite 模式(组合实体模式)
Flyweight 模式(享元模式)
Facade 模式(外观模式)//对多个类的操作进行统一管理
Proxy 模式(代理模式)//代理控制对类的创建
三、行为模式
Template 模式(模板模式)
Strategy 模式(策略模式) //通过不同策略对类进程创建
State 模式(状态模式)
Observer 模式(观察者模式)
Memento 模式(备忘录模式)
Mediator 模式(中介者模式)
Command 模式(命令模式)//对命令进行类封装
Visitor 模式(访问者模式)
Chain of Responsibility 模式(责任链模式)
Iterator 模式(迭代器模式)
Interpreter 模式(解释器模式)