vector

vector 常用操作 #include <iostream>#include <vector> int main() { //1.定义和初始化 vector<int> vec1; //默认初始化,vec1为空 vector<int> vec2(vec1); //使用vec1初始化vec2 vector<int> vec3(vec1.begin(),vec1.end());//使用vec1初始化vec2 vector<int> vec4(10); //10个值为0的元素 vector<int> vec5(10,4); //10个值为4的元素 //2.常用操作方法 //2.1 添加函数 vec1.push_back(100); // 尾部添加元素 vec1.insert(vec1.end(),5,3); // 从vec1.back位置插入5个值为3的元素 //2.2 删除函数 vec1.pop_back(); // 删除末尾元素 vec1.erase(vec1.begin(),vec1.begin()+2); // 删除vec1[0]-vec1[2]之间的元素,不包括vec1[2]其他元素前移 vec1.clear(); // 清空元素,元素在内存中并未消失,通常使用swap()来清空 vector<int>().swap(V); // 利用swap函数和临时对象交换内存,交换以后,临时对象消失,释放内存。 // 必须是同类型的 vector // 且只有存储对象时才有效 //2.3 遍历函数 vec1[0]; //取得第一个元素 vec1....

December 29, 2021 · 1 min · Rick Cui

C++ STL

STL六大组件 STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库。STL中包括六大组件:容器、算法、迭代器、适配器、仿函数、空间配置器 适配器:适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该中模式是将一个类的接口转换成客户希望的另外一个接口。 一、容器 序列式容器(vector、deque、list)、关联式容器(map、set)、容器适配器(stack、queue、priority_queue) 1. vector 是一种动态数组,在内存中具有连续的存储空间,支持快速随机访问。由于具有连续的存储空间,所以在插入和删除操作方面,效率比较慢 2. deque deque 是 double ended queue 的缩写,双向队列不论在尾部或头部插入元素,都十分迅速。而在中间插入元素则会比较费时,因为必须移动中间其他的元素。与 vector 不同,deque 不能保证将所有元素存储在连续的存储空间上 3. list list 是 STL 实现的双向链表,与 vector 相比, 它允许快速的插入和删除,但是随机访问却比较慢 4. map、multimap、unordered_map、unordered_multimap map 是 STL 的一个关联容器,它是一种键值对容器,里面的数据都是成对出现的,且键值是唯一的,可在我们处理一对一数据的时候,在编程上提供快速通道。map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的。 multimap 中的元素也是有序的,但允许存在相同键值的 unordered_map 中的元素是唯一的,但无序(也不是插入顺序),而是根据它们的散列值(hash values)组织成桶(buckets),从而允许通过键值直接快速访问单个元素(速度一般比 map 更快) unordered_multimap 无序且不唯一 5. set、multiset、unordered_set、unordered_multiset set 的含义是集合,它是一个有序的容器,里面的元素都是唯一且排序好的,支持插入、删除、查找等操作,就像一个集合一样,所有的操作都是严格在 logn时间内完成,效率非常高,使用方法类似 list multiset 也是排序好的,但是可以存有相同的元素 unordered_set 无序但元素是不可重复的 unordered_multiset 无序,元素也不唯一 二、容器适配器 虽然 stack、queue、priority_queue 中也可以存放元素,但在 STL 中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为每个容器在底层都有自己的实现方式,而 stack、queue、priority_queue 只是在底层将其他容器进行了封装 std::stack template<class T, class Container = deque<T>> class stack; std::queue template<class T, class Container = deque<T>> class queue; std::priority_queue template<class T, class Container = vector<T>, class Compare = less<typename Container::value_type>> class priority_queue; 为什么选择 deque 作为 stack 和 queue 的底层默认容器?...

December 29, 2021 · 1 min · Rick Cui

new、delete 与内存

C++ 中 new 操作符内幕:new operator、operator new、placement new 1、new / delete 具体步骤 new 第一步:调用 operator new 函数分配一块足够大的,原始的,未命名的内存空间以便存储特定类型的对象 第二步:编译器运行相应的构造函数以构造对象,并为其传入初值 第三部:对象构造完成后,返回一个指向该对象的指针 delete 第一步:调用对象的析构函数 第二步:编译器调用 operator delete 函数释放内存空间 2、new/delete 与 malloc/free 的区别是什么? malloc/free 是 C 语言的标准库函数, new/delete 是 C++ 的运算符。它们都可用于申请动态内存和释放内存 malloc/free 不会去自动调用构造和析构函数,对于基本数据类型的对象而言,光用 malloc/free 无法满足动态对象的要求 malloc/free 需要指定分配内存的大小,而 new/delete 会自动计算所需内存大小 new 返回的是指定对象的指针,而 malloc 返回的是 void*,因此 malloc 的返回值一般都需要进行强制类型转换 operator new 重载: class Person{ public: Person(){ id = 0; score = 0; cout << "Person()" << endl; } Person(int id, int score):id(id),score(score){ cout << "Person(int, int)" << endl; } Person(const Person &p){ cout << "Person(const Person &p)" << endl; id = p....

December 29, 2021 · 2 min · Rick Cui

new 二维数组

在堆上声明一个数组 int main( ) { #if 0// 方式一: int** pArr = NULL; pArr = new int*[4]; for(int i = 0; i < 4; i++){ pArr[i] = new int[8]; } for(int i = 0; i < 4; ++i){ for(int j = 0; j < 8; ++j){ pArr[i][j] = i * j; } } for(int i = 0; i < 4; ++i){ for(int j = 0; j < 8; ++j){ if(j == 0) cout << endl; cout << pArr[i][j] << '\t'; } } // 删除 for(int i = 0; i < 4; ++i){ delete [] pArr[i]; } delete [] pArr; #endif // 方式二: cout << sizeof(int[5]) << endl; // 初始化 int(*pArr)[8] = new int[4][8]; memset(pArr, 0, sizeof(int[4][8])); // 或者 // int(*pArr)[8] = new int[4][8]{{0}}; cout << sizeof(int[4][8]) << endl; for(int i = 0; i < 4; ++i){ for(int j = 0; j < 8; ++j){ pArr[i][j] = i * j; } } for(int i = 0; i < 4; ++i){ for(int j = 0; j < 8; ++j){ cout << pArr[i][j] << '\t'; } cout << endl; } cout << endl; delete[] pArr; // 取地址 int arr[3][4]{{0}}; int(*p)[3][4] = &arr; cout << arr[2][3] << endl; cout << *p[2][3] << endl; return 0; } 输出:...

December 29, 2021 · 2 min · Rick Cui

类其它总结

1. this指针 this 指针是一个隐含于每一个非静态成员函数中的特殊指针,它指向调用该成员函数的对象的首地址 当对一个对象调用成员函数时,编译程序先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时,都隐式使用 this 指针 this 指针被隐含地声明为: ClassName *const this,这意味着不能给 this 指针赋值 this 是个右值,所以不能取 this 的地址 2. delete this 类的成员函数中可以调用 delete this,但是在释放后,对象后续调用的方法不能再用到 this 指针 delete this 释放了类对象的内存空间,但是内存空间却并不是马上被回收到系统中,此时其中的值是不确定的 delete 的本质是为将被释放的内存调用一个或多个析构函数,如果在类的析构函数中调用 delete this,会陷入无限递归,造成栈溢出 3. 一个空类class中有什么? 构造函数、拷贝构造函数、析构函数、赋值运算符重载、取地址操作符重载、被 const 修饰的取地址操作符重载 4. C++ 计算一个类的 sizeof 一个空的类 sizeof 返回 1,因为一个空类也要实例化,所谓类的实例化就是在内存中分配一块地址 类内的普通成员函数不参与 sizeof 的统计,因为 sizeof 是针对实例的,而普通成员函数,是针对类体的 一个类如果含有虚函数,则这个类中有一个指向虚函数表的指针(虚函数指针),32位程序占4个字节,64位程序占8个字节 静态成员不影响类的大小,被编译器放在程序的数据段中 普通继承的类sizeof,会得到基类的大小加上派生类自身成员的大小 当存在虚拟继承时,派生类中会有一个指向虚基类表的指针。所以其大小应为普通继承的大小,再加上虚基类表的指针大小 5. 构造函数和析构函数能被继承吗? 不能。构造函数和析构函数是用来处理对象的创建和析构的,它们只知道对在它们的特殊层次的对象做什么 6. 构造函数能不能是虚函数? 不能。虚函数对应一个虚函数表,可是这个虚函数表存储在对象的内存空间的。问题就在于,如果构造函数是虚的,就需要通过 虚函数表来调用,可是对象还没有实例化,也就是内存空间还没有,就不会有虚函数表...

December 28, 2021 · 1 min · Rick Cui