C 语言跟 C++ 的差异比较
C++ 完整的 CHM 版离线手册,可以 从这里下载。
C++头文件不必是 .h 结尾
C语言中的标准库头文件,例如 math.h 和 stdio.h,在C++中被命名为 cmath 和 cstdio:
#include <cmath>
#include <cstdio>
int main() {
double a = 1.2;
a = sin(a);
printf("%lf\n", a);
}
命名空间 namespace
为了防止重名,通过 ::
运算符决定某个名字属于哪个命名空间。不加限定时,表示使用全局命名空间。
标准库中的名字,属于标准命名空间 std,例如 using std::cout
表示使用标准库中的标准输出流。
通常有三种方法使用命名空间中的某个名字:
using namespace XX; // 引入整个命名空间
using XX::name; // 引入单个名字
XX::name; // 程序中直接通过命名空间使用其中的名字
#include <cstdio>
namespace first {
int a;
void f(){}
int g(){return 666;}
}
namespace second {
double a;
double f(){return 3.14;}
char g;
}
int main() {
first::a = 2;
second::a = 3.14;
first::a = first::g() + second::f();
second::a = first::g() + 1.23;
printf("%d\n", first::a);
printf("%lf\n", second::a);
return 0;
}
输入输出流
C++ 中,输入输出都是流,通过输入输出流库(头文件 iostream),使用输出运算符 <<
和 输入运算符 >>
进行输入输出。
- cout :标准输出流对象(屏幕)
- cin:标准输入流对象(键盘)
#include <iostream>
using namespace std;
int main() {
double a;
cout << "输入一个浮点数,回车结束" << std::endl; // endl表示换行符,同时强制输出
std::cin >> a; // 从标准输入流获取输入,并存入 a
cout << a * a;
return 0;
}
引用类型
C语言中的变量都是值类型,每个变量对应一块内存。C++中引入了“引用类型”,引用类型的变量相当于一个具体的变量的“别名”。
指针 pointer 和引用 reference 的区别
- 指针是一个变量,只不过这个变量中存放的是一个地址,指向另一个内存单元。而引用跟原来的变量是同一个东西,只不过是原变量的别名。例如:
int a = 1; int *b = &a; // 指针b存放a变量的内存地址
int a = 1; int &b = a; // 引用b跟a是同一个东西,在内存中占同一个存储单元
- 指针可以有多级(存在 int **p),但引用只能有一级(不存在 int &&b)
- 可以有空指针,但是引用的值不能为NULL,且引用在定义的时候必须初始化
- 指针的值在初始化后可以改变,从而指向其他内存单元,但引用在初始化后就不能改变
- sizeof(指针) 得到指针本身的大小,sizeof(引用)得到所指向的变量或对象的大小
引用跟原变量指向同一块内存空间:
#include <iostream>
using namespace std;
int main() {
double a = 3.14;
double &b = a; // 此时没有为b分配内存空间,b跟a指向同一块内存空间
b = 666;
cout << "a now is :" << a << endl;
return 0;
}
可以通过引用进行参数传递:
#include<iostream>
using namespace std;
void test(int &x) { // 此时没有创建形参x,而是将x看做是实参的别名,x跟实参指向同一块内存空间
cout<<&x<<" "<<x<<endl;
}
int main(void) {
int a=1;
cout<<&a<<" "<<a<<endl;
test(a);
return 0;
}
C跟C++中都可以使用指针
#include <iostream>
using namespace std;
void swap(int *x, int *y) {
int t = *x;
*x = *y, *y = t;
}
int main() {
int a = 1, b = 666;
swap(&a, &b);
cout << a << " " << b << endl;
return 0;
}
可以通过 const 修饰符防止通过引用修改原变量
使用引用可以减少内存的拷贝,当对象较大时可以提高效率。为了防止使用引用后,无意中修改了原对象,可以通过 const int &x
的形式来限定:
#include <iostream>
using namespace std;
void change(int &x, const int &y, int z) {
x = 666;
y = 667; // error: assignment of read-only reference 'y'
z = 668;
}
int main() {
int a = 1, b = 2, c;
change(a, b, c);
cout << a << " " << b << " " << c << endl;
return 0;
}
内联函数
用 inline
关键字声明的函数称为内联函数。编译器碰到内联函数时,会用函数的代码替换这个函数,称为“内敛展开”,从而避免了函数调用的开销,提高程序执行效率。
#include <iostream>
#include <cmath>
using namespace std;
inline double area(double x, double y) {
return sqrt(x * x + y * y);
}
int main() {
double a = 3, b = 4;
cout << area(a, b) << endl;
return 0;
}
try-catch 异常处理机制
C++支持异常处理。异常事件发生时用 throw 关键字抛出异常表达式,抛出点称为异常出现点,由操作系统为程序设置当前异常对象,然后执行异常处理代码,顺序如下:
- 执行当前异常处理代码块,依次匹配catch语句中的异常对象(只进行类型匹配)。
- 若匹配成功,则执行catch块内的异常处理语句,然后接着执行try…catch…块之后的代码。
- 如果在当前的try…catch…块内找不到匹配该异常对象的catch语句,则由更外层的try…catch…块来处理该异常。
- 如果当前函数内所有的try…catch…块都不能匹配该异常,则递归回退到调用栈的上一层去处理该异常。
- 如果一直到主函数main()都不能处理该异常,则调用系统函数terminate()终止程序。
#include <iostream>
using namespace std;
int main() {
int score = 0;
try {
cin >> score;
if (socre > 100 || score < 0) throw score;
cout << "分数保存成功“;
} catch (int score) {
cerr << "请输入 0 - 100 之间的分数" << endl;
}
}
默认形参
C++ 中,函数的参数可以带默认值,带默认值的参数必须放在最右边:
void test(int a, int b = 10, int c = 20) {...}
函数重载
C++ 中允许函数重名,只要形参不一样(个数或类型不一样)。调用函数时会根据实参和形参自动匹配最佳的函数。
#include <iostream>
using namespace std;
void test(int a, int b) {
cout << a + b << endl;
}
void test(int a, double b) {
cout << a + b << endl;
}
int main() {
test(3, 3.14);
test(3, 5);
return 0;
}
运算符重载
重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
#include <iostream>
using namespace std;
struct Vector2{
double x;
double y;
};
Vector2 operator * (double a, Vector2 b) {
Vector2 r;
r.x = a * b.x;
r.y = a * b.y;
return r;
}
int main() {
Vector2 b, k;
b.x = 3.14;
b.y = 6.66;
k = 3.14 * b;
cout << k.x << endl;
}
template 模板
C++ 是强类型的语言,函数或类需要针对每一种具体类型进行操作时,代码大量冗余。通过模板类或模板函数,可以编写不针对某一具体类型的代码,编译器在编译时,可以针对具体数据类型,自动用模板函数生成针对该具体数据类型的函数或类。
可以参考 C++ Template 进阶指南。
模板函数
模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。
模板是创建泛型类或函数的蓝图。库容器比如迭代器和算法,都是泛型编程的例子,使用了模板的概念。
每个容器都有一个单一的定义,比如 向量,我们可以定义许多不同类型的向量,比如 vector 或 vector 。
模板函数定义如下,其中 type 是函数所使用的数据类型的占位符名称。这个名称可以在函数定义中使用:
template <class type> ret-type func-name(parameter list)
{
// 函数主体
}
求不同数据类型最小值的模板函数:
#include <iostream>
using namespace std;
template <class T>
T minVal(T a, T b) {
return a > b ? b : a;
}
int main() {
int a = 3, b = 4;
cout << "min of int is: " << minVal(a, b) << endl;
double x = 3.14, y = 666;
cout << "min of double is: " << minVal(x, y) << endl;
}
上面例子中,当两个数的类型也不同时,编译时会报错。要增加对不同类型数据的比较功能,需要改写一下:
#include <iostream>
using namespace std;
template <class T, class U>
T minVal(T a, U b) {
return a > b ? b : a;
}
int main() {
int a = 3, b = 4;
cout << "min of int is: " << minVal(a, b) << endl;
double x = 3.14, y = 666;
cout << "min of double is: " << minVal(x, y) << endl;
cout << "min of mix is: " << minVal(a, y) << endl;
}
动态内存分配
C语言中通过 malloc/alloc/realloc 和 free 分配和释放内存(在堆存储区)。C++ 则通过 new 和delete 进行,会自动调用构造函数和析构函数。
#include <iostream>
#include <cstring>
using namespace std;
int main() {
double d = 3.14;
double *p = &d;
cout << *p << " " << p << endl;
p = new double;
*p = 3.1415926;
cout << *p << " " << p << endl;
delete p;
p = new double[4];
p[0] = 6.66;
p[1] = 7.77;
cout << p[0] << " " << *(p+1) << endl;
delete[] p;
char *s = new char[100];
strcpy(s, "hello world");
cout << s << endl;
}
struct 类定义
C++ 的 struct 中支持成员函数和成员变量
// class templates
#include <iostream>
using namespace std;
struct Date {
int y, m, d;
void print() {
cout << y << "-" << m << "-" << d << endl;
}
void init(int yy, int mm, int dd) {
y = yy; m = mm; d = dd;
}
};
int main () {
Date date;
date.y = 2000;
date.print();
date.init(2000, 8, 15);
date.print();
return 0;
}
this 指针
在类中可以使用 this 指针来表示类本身。
#include <iostream>
using namespace std;
struct Date {
int y, m, d;
void print() {
cout << y << "-" << m << "-" << d << endl;
}
void init(int yy, int mm, int dd) {
y = yy; m = mm; d = dd;
}
Date& add(int a) {
d += a;
return *this;
}
};
int main () {
Date date;
date.init(2000, 8, 15);
date.print();
date.add(3).add(5);
date.print();
return 0;
}
构造函数
C++ 的类中,与类名同名,且没有返回值的函数就是构造函数。函数初始化时会首先自动调用构造函数。
不需要任何参数的构造函数称为默认构造函数。如果没有定义任何构造函数,则编译器会自动生成默认构造函数。只要定义了自己的构造函数,则不再存在默认构造函数,如果需要,必须自己定义。
#include <iostream>
using namespace std;
struct Date {
int y, m, d;
void print() {
cout << y << "-" << m << "-" << d << endl;
}
Date() {
y = 2018; m = 1; d = 1;
}
Date(int yy, int mm, int dd) {
y = yy; m = mm; d = dd;
}
Date& add(int a) {
d += a;
return *this;
}
};
int main () {
Date date1;
date1.print();
Date date(2000, 8, 15);
date.print();
date.add(3).add(5);
date.print();
return 0;
}
构造函数中,可以使用默认值:
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int age;
char * name;
Student(char * n = "no_name", int a = 18) {
// *name = *n;
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
};
int main () {
Student s1;
cout << s1.name << "\t" << s1.age << endl;
Student s2("lisi");
cout << s2.name << "\t" << s2.age << endl;
Student s3("zs", 33);
cout << s3.name << "\t" << s3.age << endl;
return 0;
}
析构函数
C++ 中,类的同名函数前加 virtual ~
表示是析构函数。析构函数在类销毁前自动调用,用于执行清理任务(例如关闭打开的文件、网络,释放内存等)。
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int age;
char * name;
Student(char * n = "no_name", int a = 18) {
// *name = *n;
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
virtual ~Student() {
cout << name << " destroctur" << endl;
delete[] name;
}
};
int main () {
Student s1;
cout << s1.name << "\t" << s1.age << endl;
Student s2("lisi");
cout << s2.name << "\t" << s2.age << endl;
Student s3("zs", 33);
cout << s3.name << "\t" << s3.age << endl;
return 0;
}
拷贝构造函数
定义类对象时,可以用同类型的已有对象进行初始化,此时编译器会自动创建拷贝构造函数并调用。
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int age;
char * name;
Student(char * n = "no_name", int a = 18) {
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
virtual ~Student() {
cout << name << " destroctur" << endl;
delete[] name;
}
};
int main () {
Student s1;
Student s2(s1);
cout << s2.name << "\t" << s2.age << endl;
return 0;
}
也可以自己实现拷贝构造函数:
Student(const Student &s) {
name = new char[100];
strcpy(name, s.name);
age = s.age;
cout << "这是拷贝构造函数" << endl;
}
类的赋值
可以使用赋值运算符,将一个对象赋值给另一个对象。
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int age;
char * name;
Student(char * n = "no_name", int a = 18) {
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
virtual ~Student() {
cout << name << " destroctur" << endl;
delete[] name;
}
};
int main () {
Student s1;
Student s2 = s1;
cout << s2.name << "\t" << s2.age << endl;
return 0;
}
也可以自己实现赋值运算符:
Stuednt& operator = (const Student &s) {
name = new char[100];
strcpy(name, s.name);
age = s.age;
cout << “自己的赋值运算符" << endl;
return *this;
}
拷贝构造函数和赋值运算符的完整例子
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
int age;
char * name;
Student(char * n = "no_name", int a = 18) {
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
virtual ~Student() {
cout << name << " destroctur" << endl;
delete[] name;
}
Student& operator = (const Student &s) {
name = new char[100];
strcpy(name, s.name);
age = s.age;
cout << "自己的赋值运算符" << endl;
return *this;
}
Student(const Student &s) {
name = new char[100];
strcpy(name, s.name);
age = s.age;
cout << "这是拷贝构造函数" << endl;
}
};
int main () {
Student s1;
Student s2(s1);
s2 = s1;
cout << s2.name << "\t" << s2.age << endl;
return 0;
}
输出:
这是拷贝构造函数
自己的赋值运算符
no_name 18
no_name destroctur
no_name destroctur
类成员的访问控制及接口访问
C++ 的可见性限定符有3中:
名称 | 可见性 |
---|---|
public | 所有地方都可以访问 |
private | 仅类自身可以访问 |
protect | 仅类及其子类可以访问 |
通常,属性不可以直接暴露在外部,而是通过接口来访问(查看或修改)。
在类的外部定义成员函数
C++要求使用前先声明。如果把成员定义放到类声明中,当类中的两个定义互相调用时,那么这两个声明无论谁先后,最先的那个总是使用到了未声明的符号;如果把成员定义和类声明分开,就可以在定义使用之前把所需的声明全列出来。
类的成员函数,包括构造函数,都可以在类的外部定义(方法名前需要加 类名::
),但是需要在类的内部声明。
#include <iostream>
#include <cstring>
using namespace std;
struct Student {
private:
int age;
char * name;
public:
Student(char * n = "no_name", int a = 18) {
int len = strlen(n);
name = new char[len + 1];
strcpy(name, n);
age = a;
}
virtual ~Student() {
delete[] name;
}
char * getName();
};
char * Student::getName() {
return name;
}
int main () {
Student s1("xiaoming");
// cout << s1.name << "\t" << s1.age << endl;
cout << s1.getName() << endl;
return 0;
}
类模板
参考 这里
C++ 是强类型的语言。如果针对每种类型写一个类,冗余太高,所以有了类模板。
类模板是忽略具体类型的公共逻辑的抽象,通常用来作为容器(例如:vector)或者行为(例如:clonable)的封装。最简单的例子:
#include <iostream>
using namespace std;
template <class T>
class myT {
public:
T max(T a, T b) {
return a > b ? a : b;
}
};
int main() {
myT<int> m1;
cout << m1.max(1, 2) << endl;
return 0;
}
与模板函数不同,类模板不能推断实例化。所以必须在实例化时显式指定类型参数,例如:Printer<int> p(1)
,而不能让编译器自行推断 Printer p(1)
。
#include <iostream>
using namespace std;
template <class T>
class mypair {
T a, b;
public:
mypair (T first, T second)
{a=first; b=second;}
T getmax ();
};
template <class T>
T mypair<T>::getmax ()
{
T retval;
retval = a>b? a : b;
return retval;
}
int main () {
mypair <int> myobject (100, 75);
cout << myobject.getmax();
return 0;
}
类型别名 typedef
参考 C++ typedef用法小结。
typedef 用于为已有的类型创建别名。
typedef是定义了一种类型的新别名,#define 则是简单的字符串替换。
#include <iostream>
#include <typeinfo>
using namespace std;
typedef char * PCHAR; // 一般大写
int main() {
char * p1, p2;
// p1 是字符指针类型,p2 是字符类型
cout << typeid(p1).name() << " " << typeid(p2).name() << endl;
PCHAR p3, p4;
// p3 p4 都是字符指针类型
cout << typeid(p3).name() << " " << typeid(p4).name() << endl;
return 0;
}
C++中的 string
C++ 支持 C 风格的字符串(用 null 字符 ‘\0’ 终止的一维字符数组),同时还引入了 string 类类型。
- C 风格:
可以引入 cstring 这个 C 语言的字符串库,使用 strcpy、strlen、strcat、strcmp 等方法:
#include <iostream>
using namespace std;
int main() {
char str[] = "hello world";
char str2[3] = "AB"; // 结束字符占一个字符,所以这里最多放两个
cout << str << endl;
cout << str2 << endl;
cout << str[2] << endl;
return 0;
}
- String 类:
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "hello world";
cout << str << endl;
string str2("ABC");
cout << str2 << endl;
string str3(str);
cout << str3 << endl;
string str4(str.begin(), str.end()-2);
cout << str4 << endl;
string str5(str, 5);
cout << str5 << endl;
cout << str.size() << endl;
cout << str + str2 << endl;
}
输出:
hello world
ABC
hello world
hello wor
world
11
hello worldABC
STL
STL:标准模板库(Standard Template Library),是 C++ 内置支持的库。STL 利用的 C++ 的类模板和函数模板机制,由容器、算法和迭代器组成。
容器
容器::数据存储上,有一种对象类型,它可以持有其他对象或指向其他对象的指针,这种对象类型叫容器。
容器就是保存其他对象和相关方法的对象,是对特定代码重用问题的良好的解决方案。
STL 提供的容器有:
- 顺序容器:线性表结构
- vector容器:从后面快速插入和删除,访问任一元素
- deque双端数组:从前后两侧快速插入和删除,访问任一元素
- list链表:从任何位置插入和删除
- 关联容器:二叉树结构
- set容器:快速查找,不允许重复值
- multiset容器:快速查找,允许重复值
- map容器:一对多映射,基于关键字快速查找,不允许重复值
- multimap容器:一对多映射,基于关键字快速查找,允许重复值
- 容器适配器:接口转换
- stack栈模型:先进后出
- queue队列模型:先进先出
- priotriy_queue优先级队列:最高优先级的先出
Vector 容器
向量(Vector)是一个封装了动态大小的数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。
vector 在尾部添加或者移除元素非常快,中间元素的操作非常耗时,因为需要移动元素。
优缺点:
- 检索效率高
- 操作最后一个元素效率高
- 操作中间元素效率差
- 一旦需要重新分配空间,则性能很差
相关函数
- 构造函数
vector():创建一个空vector
vector(int nSize):创建一个vector,元素个数为nSize
vector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为t
vector(const vector&):拷贝构造函数
vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中
- 增删元素
void push_back(const T& x):向量尾部增加一个元素X
iterator insert(iterator it,const T& x):向量中迭代器指向元素前增加一个元素x
iterator insert(iterator it,int n,const T& x):向量中迭代器指向元素前增加n个相同的元素x
iterator insert(iterator it,const_iterator first,const_iterator last):向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据
iterator erase(iterator it):删除向量中迭代器指向元素
iterator erase(iterator first,iterator last):删除向量中[first,last)中元素
void pop_back():删除向量中最后一个元素
void clear():清空向量中所有元素
- 迭代
reference at(int pos):返回pos位置元素的引用,比 [] 数组方式多了越界校验
reference front():返回首元素的引用
reference back():返回尾元素的引用
iterator begin():返回向量头指针,指向第一个元素
iterator end():返回向量尾指针,指向向量最后一个元素的下一个位置
reverse_iterator rbegin():反向迭代器,指向最后一个元素
reverse_iterator rend():反向迭代器,指向第一个元素之前的位置
- 其他
bool empty() const:判断向量是否为空,若为空,则向量中无元素
int size() const:返回向量中元素的个数
int capacity() const:返回当前向量张红所能容纳的最大元素值
int max_size() const:返回最大可允许的vector元素数量值
void swap(vector&):交换两个同类型向量的数据
void assign(int n,const T& x):设置向量中第n个元素的值为x
void assign(const_iterator first,const_iterator last):向量中[first,last)中元素设置成当前向量元素
示例
#include <vector>
#include <iostream>
#include <algorithm>
#include <stdexcept>
#include <iterator>
using namespace std;
int main(int argc, const char * argv[]) {
const int SIZE = 6;
int array[SIZE] = {1, 2, 3, 4, 5, 6};
vector<int> v(array, array + SIZE);
cout << "first element:" << v.front() << " last:" << v.back() << endl;
v[1] = 7;
v.at(2) = 8;
v.insert(v.begin() + 2, 18);
v.push_back(666); // weibu尾部zhuij尾部追加yuansu
vector<int>::iterator it;
it = v.begin();
while(it != v.end()) {
cout << *it << endl;
it++;
}
it = find(v.begin(), v.end(), 22);
if (it != v.end())
cout << "location is: " << (it - v.begin()) << endl;
else
cout << "not found" << endl;
cout << "max size is:" << v.max_size() << endl;
cout << "capacity is:" << v.capacity() << endl;
try {
v.at(666) = 777;
} catch (out_of_range & e) {
cout << "Exception: " << e.what() << endl;
}
v.erase(v.begin());
v.erase(v.begin(), v.end());
cout << (v.empty() ? "yes empty" : "not empty") << endl;
}
list 容器
list 容器是双向线性链表结构,指针将所有元素链接起来。
优缺点:
- 检索效率差,需要顺序查找,迭代器只能 ++,不能一次性跳转
- 增删元素效率高
相关函数
pop_back() 删除最后一个元素
pop_front() 删除第一个元素
push_back() 在list的末尾添加一个元素
push_front() 在list的头部添加一个元素
示例
int main(int argc, const char * argv[]) {
list<int> l; //创建list对象
//尾部添加元素
for (int i = 0; i < 10; i++) {
l.push_back(i);
}
//头部添加元素
l.push_front(111);
//删除头部元素
l.erase(l.begin());
//删除某个区间
list<int>::iterator it = l.begin();
it++;
it++;
it++;
l.erase(l.begin(), it);
//移除值为100的所有元素
l.remove(100);
//遍历
for (list<int>::iterator it = l.begin(); it != l.end(); it++) {
cout << *it << " ";
}
cout << endl;
return 0;
}
map 容器
stack 容器操作跟堆栈一样,都支持入栈和出栈。
相关函数
insert() 插入元素
key_comp() 返回比较元素key的函数
lower_bound() 返回键值>=给定元素的第一个位置
示例
set 容器
set 是包含有序对象的关联容器,默认的顺序是从小到大的。
相关函数
count(): 返回某个值元素的个数
empty(): 如果集合为空,返回true
erase(): 删除集合中的元素
insert(): 在集合中插入元素
max_size(): 返回集合能容纳的元素的最大限值
size(): 集合中元素的数目
swap(): 交换两个集合变量
value_comp(): 返回一个用于比较元素间的值的函数
示例
void main()
{
//默认,从小到大
set<int> set1;
set<int, less<int>> set2;
//从大到小
set<int, greater<int>> set3;
//添加元素
for (int i = 0; i < 5; i++) {
int tmp = rand();
set3.insert(tmp);
}
//遍历
for (set<int>::iterator it = set3.begin(); it != set3.end(); it++) {
cout<< *it << " ";
}
}
deque 容器
deque 是一个双端数组容器,可以在头部和尾部操作元素。
相关函数
void push_back(const T& x):deque尾部增加一个元素X
void pop_back():删除deque中最后一个元素
void push_front(const T& x):deque头部增加一个元素X
void pop_front():删除deque中第一个元素
示例
stack 容器
stack 容器操作跟堆栈一样,都支持入栈和出栈。
相关函数
empty() 堆栈为空则返回真
pop() 移除栈顶元素
push() 在栈顶增加元素
size() 返回栈中元素数目
top() 返回栈顶元素
示例
算法
STL 包含一些独立函数(称为算法)用来操作容器。需要引入 algorithm 头文件后使用。
例如,find 查找算法,找到元素则返回元素的迭代器,否则返回改容器最后一个元素之后的位置(即 v.end()
)。copy 复制算法,将容器或其一部分复制到另一个容器中。
迭代器
使用迭代器,可以对容器元素进行枚举遍历。迭代器定义在 中。
迭代器相当于指针,可以进行解引用(求出指针所指向变量的值,*p)和算术运算。
迭代器的声明
迭代器有4中不同声明方式,第一种最常用:
iterator:前项遍历,可读可写
const_iterator:前项遍历,只读
reverse_iterator:后向遍历,可读可写
const_reverse_iterator:后向遍历,只读
迭代器函数
假设 v 是某个实例化的容器,例如 vector<int> v()
,则:
v.begin():返回指向容器首元素的迭代器
v.end():返回指向容器尾元素的下一个位置的迭代器
v.rbegin():返回指向容器最后一个元素的反向迭代器
v.rend():返回指向容器第一个元素之前的位置的反向迭代器
类的继承
虚函数和多态
抽象类
C 语言跟 C++ 的差异比较的更多相关文章
- 一.OC基础之:1,OC语言的前世今生 ,2,OC语言入门,3,OC语言与C的差异,4,面向对象,5,类和对象的抽象关系,6,类的代码创建,7,类的成员组成及访问
1,OC语言的前世今生 , 一, 在20世纪80年代早期,布莱德.麦克(Brad Cox)设计了OC语言,它在C语言的基础上增加了一层,这意味着对C进行了扩展,从而创造出一门新的程序设计语言,支持对象 ...
- C语言和单片机C语言为什么会有差异?虽不同但理同!
许多小伙伴在学完C语言后想入门单片机,但学着学着发现明明都是C语言,为什么单片机C语言和我当初学的C语言有差异呢? 今天小编就来梳理我们平时所学的C语言与单片机C语言的有什么样的不同. 单片机c语言比 ...
- 【Shell脚本学习2】Shell脚本语言与编译型语言的差异
大体上,可以将程序设计语言可以分为两类:编译型语言和解释型语言. 编译型语言 很多传统的程序设计语言,例如Fortran.Ada.Pascal.C.C++和Java,都是编译型语言.这类语言需要预先将 ...
- 【转】shell 教程——03 Shell脚本语言与编译型语言的差异
大体上,可以将程序设计语言可以分为两类:编译型语言和解释型语言. 编译型语言 很多传统的程序设计语言,例如Fortran.Ada.Pascal.C.C++和Java,都是编译型语言.这类语言需要预先将 ...
- Shell脚本语言与编译型语言的差异
大体上,可以将程序设计语言可以分为两类:编译型语言和解释型语言. 编译型语言 很多传统的程序设计语言,例如Fortran.Ada.Pascal.C.C++和Java,都是编译型语言.这类语言需要预先将 ...
- 【转载】Java与C++语言在作用域上的差异浅析
http://developer.51cto.com/art/200906/126199.htm 差异一:变量作用域的不同 如下面这段程序代码是符合C++语言的语法要求的.其可以在C语言下正常运行.但 ...
- R语言笔记
R语言笔记 学习R语言对我来说有好几个地方需要注意的,我觉得这样的经验也适用于学习其他的新的语言. 语言的目标 我理解语言的目标就是这个语言是用来做什么的,为什么样的任务服务的,也就是设计这个语言的动 ...
- [转]Go与C语言的互操作
Go有强烈的C背景,除了语法具有继承性外,其设计者以及其设计目标都与C语言有着千丝万缕的联系.在Go与C语言互操作(Interoperability)方面,Go更是提供了强大的支持.尤其是在Go中使用 ...
- C# 与 Java 的一些差异
如果你是 Java 开发人员,则可以在 Xamarin 平台上充分利用你的技能和现有代码,同时获得 C# 的代码重用优势.你会发现 C# 语法与 Java 语法非常相似,这两种语言提供非常类似的功能. ...
随机推荐
- ECMAScript(ES) 6 之 let 与 const
ES6 新增加了两个重要的 JavaScript 关键字 :let 和 const 先说一下 const :它用于声明一个只读的常量,一旦声明,常量的值就不能改变. const servicePat ...
- Bootstrap table 实现树形表格,实现联动选中,联动取消
公司最近有需求要做树形式table.因为是前后端不分离项目,且之前已经引入了bootstrap table插件,现把实现方式分享一下: <!DOCTYPE HTML> <html l ...
- 为什么我选择用 flutter
1. flutter 生成的是机器代码,他既不是 hybrid 也不是transpiler, 因此有很高的执行效率. 2. declarative ui,这不是什么新的概念,在 react vue ...
- snmpwalk工具使用
snmpwalk是SNMP的一个工具,它使用SNMP的GETNEXT请求查询指定OID(SNMP协议中的对象标识)入口的所有OID树信息,并显示给用户. 在linux下使用snmpwalk工具,我们 ...
- Proxy + Reflect 实现 响应的数据变化
Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等) let p = new Proxy(target, handler); get(target, propKey, r ...
- 谷歌浏览器遇到js报错自动进行断点调试,如何关闭
转载于csdn 附地址 http://blog.csdn.net/microcosmv/article/details/60793882 留备用.
- 关于在IOS中 contenteditable=true 无法输入的问题
解决: 1.添加样式-webkit-user-select:text 2.如果引入了fastclick,需要添加个类名 needsclick 来源于知乎(https://www.zhihu.com/q ...
- getopt:命令行选项、参数处理
在写shell脚本时经常会用到命令行选项.参数处理方式,如: ./test.sh -f config.conf -v --prefix=/home -f 为短选项,它需要一个参数,即config.co ...
- 【leetcode】1163. Last Substring in Lexicographical Order
题目如下: Given a string s, return the last substring of s in lexicographical order. Example 1: Input: & ...
- python frozenset集合(17)
在前一篇文章中我们对 python set集合 做了详细的讲解,而本文讲解的 frozenset集合 其实和set集合类似!区别在于frozenset集合不能修改/添加/删除,其他功能和set集合一样 ...