一、模板 template
1.1概念
C++重模板可以让类或函数声明一种通用类型,使得函数或类中的某些成员变量或成员变量的参数、返回值在实际上的使用中可以是任何类型。
模板可以让程序员写出与类型无关的代码,是泛型编程的基础。
模板主要分为两种实现方式:
- 函数模板
- 类模板
1.2函数模板
#include <iostream>
using namespace std;
// 函数模板
template <class T>
T add(T a,T b)
{
return a+b;
}
class Dog
{
};
int main()
{
// 在使用的过程中T可以任何类型
cout << add(2,3) << endl;
cout << add(2.2,2.2) << endl;
cout << add('0','0') << endl;
// 这套通用算法可能不支持某些类型
// 错误出现的原因并非不能传参,而是不能计算
cout << add("aa","aa") << endl; // const char*
Dog d1;
Dog d2;
add(d1,d2);
return 0;
}
1.3类模板
#include <iostream>
using namespace std;
template <typename T>
class Demo
{
private:
T value;
public:
Demo(T value):value(value){}
T get_value() const
{
return value;
}
};
class MobilePhone
{
private: // 私有:被修饰的成员只能在类内访问
string brand; // 读写
string model = "16"; // 只读
int weight; // 只写
public:
string get_brand() // getter:读函数
{
return brand;
}
void set_brand(string b) // setter:写函数
{
brand = b;
}
string get_model()
{
return model;
}
void set_weight(int w)
{
weight = w;
}
};
int main()
{
// 类模板在创建对象时要标注T的具体类型,以便于开辟内存
Demo<int> d1(1);
cout << sizeof(d1) << " " << d1.get_value() << endl; // 4 1
Demo<long> d2(1);
cout << sizeof(d2) << " " << d2.get_value() << endl; // 4 1
MobilePhone mp1;
Demo<MobilePhone> d3(mp1);
cout << sizeof(d3) << endl; // 12
return 0;
}
include <iostream>using namespace std;
template <typename T>
class Demo
{
private:
T value;
public:
Demo(T value);
T get_value() const;
};
template <typename T>
Demo<T>::Demo(T value)
{
this->value = value;
}
template <typename T>
T Demo<T>::get_value() const
{
return value;
}
class MobilePhone
{
private: // 私有:被修饰的成员只能在类内访问
string brand; // 读写
string model = "16"; // 只读
int weight; // 只写
public:
string get_brand() // getter:读函数
{
return brand;
}
void set_brand(string b) // setter:写函数
{
brand = b;
}
string get_model()
{
return model;
}
void set_weight(int w)
{
weight = w;
}
};
int main()
{
// 类模板在创建对象时要标注T的具体类型,以便于开辟内存
Demo<int> d1(1);
cout << sizeof(d1) << " " << d1.get_value() << endl; // 4 1
Demo<long> d2(1);
cout << sizeof(d2) << " " << d2.get_value() << endl; // 4 1
MobilePhone mp1;
Demo<MobilePhone> d3(mp1);
cout << sizeof(d3) << endl; // 12
return 0;
}
二、容器
1 .1STL标准模板库
标准模板库(Standard Template Library,STL)是惠普实验室开发的一系列软件的统称。虽说它主要表出现到C++中,但在被引入C++之前该技术就已经存在了很长时间。STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
1.2容器的概念
容器是存储数据的集合,存储的数据元素可以是任何类型,因为容器是模板实现的。容器类对象只能使用栈内存,不支持堆内存。另外,容器类的使用都需要引入对应的头文件。
1.3顺序容器
顺序容器是一种线性结构的可序群集,但是可以通过插入或删除(array不支持)等操作改变元素的位置。
2.1array(C++11)
#include <iostream>
#include <array> // 头文件
using namespace std;
int main()
{
array<int,5> arr; // 创建一个长度为5的int数组
// 赋值
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
// 修改
arr.at(2) = 222;
arr[3] = 333;
// cout << arr.at(-3248673) << endl; 崩溃
// 遍历输出
for(int i =0;i<arr.size();i++)
{
cout << arr[i] << " ";
}
cout << endl;
arr.fill(666); // 更改所有元素的值
for(int i:arr)
cout << i << " ";
cout << endl;
return 0;
}
2.4vector
vector内部通过数组实现,但是vector是可变长的,因此每次长度变化时,内部重新创建数组,能高效地进行随机存取(数组的内存连续),但是不擅长插入删除。
#include <iostream>
#include <vector> // 头文件
using namespace std;
int main()
{
vector<int> vec1; // 创建一个长度为0的对象
cout << vec1.empty() << endl; // 1
vector<int> vec2(5); // 创建一个长度为5的对象
for(int i=0;i<vec2.size();i++)
cout << vec2.at(i) << " "; // 0 0 0 0 0
cout << endl;
vector<int> vec3(vec2); // 拷贝构造
for(int i:vec3)
cout << i << " ";
cout << endl;
// 参数1:长度
// 参数2:默认值
vector<string> vec4(5,"AAA");
// 增加元素
vec4.push_back("BBB"); // 尾插
// 在第二个位置插入元素
// begin返回一个迭代器指针,指向第一个元素
vec4.insert(vec4.begin()+1,"No.2");
// 在倒数第三个位置插入元素
// end返回一个迭代器指针,指向最后一个元素的后面
vec4.insert(vec4.end()-2,"No.-3");
// 删除数据
vec4.pop_back(); // 删除最后一个数据
// 删除第一个数据
vec4.erase(vec4.begin());
// 删除倒数第一个数据
vec4.erase(vec4.end()-1);
// 删除所有元素
vec4.clear();
for(string i:vec4)
cout << i << " ";
cout << endl;
// 迭代器(略)
return 0;
}
2.5list
#include <iostream>
#include <list> // 头文件
using namespace std;
int main()
{
list<int> lis1; // 创建一个长度为0的对象
cout << lis1.empty() << endl; // 1
list<int> lis2(5); // 创建一个长度为5的对象
cout << endl;
list<int> lis3(lis2); // 拷贝构造
for(int i:lis3)
cout << i << " ";
cout << endl;
// 参数1:长度
// 参数2:默认值
list<string> lis4(5,"AAA");
// 增加元素
lis4.push_back("BBB"); // 尾插
// 在第二个位置插入元素
// begin返回一个迭代器指针,指向第一个元素
lis4.insert(++lis4.begin(),"No.2");
// 在倒数第三个位置插入元素
// 存储迭代器指针
list<string>::iterator iter = lis4.end();
// 移动迭代器指针,-2表示向前移动两位
advance(iter,-2);
// end返回一个迭代器指针,指向最后一个元素的后面
lis4.insert(iter,"No.-3");
// 删除数据
lis4.pop_back(); // 删除最后一个数据
// 删除第一个数据
lis4.erase(lis4.begin());
// 删除倒数第一个数据
lis4.erase(--lis4.end());
// 删除所有元素
// lis4.clear();
// 头插
lis4.push_front("头");
// 删除第一个元素
lis4.pop_front();
// 取出第一个和最后一个元素的引用
cout << lis4.front() << " " << lis4.back() << endl;
// 排序(升序)
lis4.sort();
for(string i:lis4)
cout << i << " ";
cout << endl;
// 迭代器(略)
return 0;
}
2.6deque
插入删除和随机存取的性能介于vector和list之间,擅长两端存取,API几乎兼容vector和list。