1.vector的求长度size()-1
例1:
for (int i = 0; i <v.size()-1; ++i) {
代码段A;
}
例2:
vector vec = {};
int i = vec.size() - 1;
cout << i << endl;
cout << vec.size() - 1;
得到的结果上面是-1,下面却是4294967295
其中v是一个变长数组vector类型,按照道理来说,当v的长度为0时,v.size()-1的值为-1,循环不会开始,代码段A不会执行,但是我在调试的过程中,发现当v的长度为0时,代码段A也会执行,后来查阅资料发现,在STL中,无论什么数据类型,size()函数返回的类型是一个无符号整形(unsigned)(vector.size 返回值就是 size_t
而size_t定义就是 typedef unsigned int size_t) ,当size()为0时,返回值是00000000 00000000 00000000 00000000(32位,32个0),而该值减1时,由计算机组成的原理知,CPU的ALU没有减法器,只有加法器,所以变成+(-1)运算,可是-1在内存中的值为11111111
11111111 11111111 11111111(32位,32个1,补码),而一个无符号数加一个有符号数,CPU直接把它们当两个无符号数,相加的结果为11111111 11111111 11111111 11111111(32位,32个1,无符号整数),转为10进制是4294967295,所以0-1没有变成-1,而是变成了一个很大的数,因而代码段A会被执行了。
用如下代码可以输出这个值:
#include<vector>
#include<iostream>
using namespace std;
int main() {
vector<int> v;
cout << v.size() - 1;
}
结果正是4294967295。其实这个结果并不唯一,取决于你的计算机的无符号整数的位数,32位就是2^32-1,64位就是2^64-1。
看来学计算机组成也是很有必要的。
2.STL的sort相关:
https://blog.csdn.net/qq_43827595/article/details/104242037
a.在class类中的sort函数的参数cmp,定义时要声明为static
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);可以知道其实我们写参数cmp时,是把函数名作为实参传递给了sort函数,而sort函数内部是用一个函数指针去调用这个cmp函数的(建议先看下 一文搞懂什么是 函数指针 ),我们知道class普通类成员函数cmp需要通过对象名.cmp()来调用,而sort()函数早就定义好了,那个时候哪知道你定义的是什么对象,所以内部是直接cmp()的,那你不加static时,去让sort()直接用cmp()当然会报错
static静态成员函数不用加对象名,就能直接访问函数(这也是静态成员函数的一大优点)所以加了static就不会报错
https://blog.csdn.net/qq_35440678/article/details/80147601
3.list使用size()会时间过长
4.map和set小坑
3中方法将自定义类或结构体作为key(<操作符,仿函数comp,作为指针)
a1.对于set和map容器,key需要有<操作符或者自定义比较函数(如:类和结构体作为key值)
https://blog.csdn.net/zhubaohua_bupt/article/details/62036499
a2.如果需要用结构体指针作为key值得话,是用地址来查找比较,相同得话返回true,如果需要依据其中参数来查找,需要传入自定义仿函数(比如如果传入得)
https://blog.csdn.net/fengfengdiandia/article/details/87403713
经过测试,类指针可以直接作为key,通过地址来查找,如果地址不变化得话能找到(insert 右值时,会找不到,但不是明明得么。。。,因为根据地址找的)
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <utility>
using namespace std;
typedef struct {
std::string name;
int age;
} Person;
struct comp {
bool operator()(const Person *p1, const Person *p2) const {
return !(p1->name == p2->name && p1->age == p2->age);
}
};
typedef std::map<Person *, int, comp> ScoreMap;
//typedef std::map<Person *, int> ScoreMap;
void find(ScoreMap *m, Person *p2) {
auto it = m->find(p2);
if (it != m->end()) {
std::cout << "Found! name=" << p2<<it->first->name << ", age="
<< it->first->age << ", score=" << it->second << "\n";
} else {
std::cout << "Not found, "<< p2<<"{" << p2->name << ", " << p2->age << "}\n";
}
}
int main() {
ScoreMap m;
Person p1{"Aland", 18};
m.insert(make_pair(new Person{"Aland",18},500)); //here if not make comp,so cant find,because its new,rvalve
find(&m,&p1);
Person p2{"Aland", 18};
m[&p2] = 50;
find(&m, &p2); //after send p2 to function,the addr change,so cant find if not make new comp
Person p3{"Jack", 20};
find(&m, &p3);
cout <<"p2 addr:"<<&p2<<" p3 addr:"<< &p3<<endl;
return 0;
}
b.map
如果使用operator[]操作,会覆写对应下标里面的值,所以如果使用xx_map[key]判断时会创建一个空的对象。
使用insert时,如果有对应的key,则不会去覆写对应的值,结果就是,如果有对应的key则没插进去。
如果一个key存在, operator[] 对这个key-value进行重写
如果一个key存在, insert 不会对原来的key-value进行重写
c.set
set中的iterator和const_iterator时一样的,都是const类型。所以存入set中的元素都会转换为const类型。
转载于:https://my.oschina.net/mskk/blog/3001703
5.vector 二维数组相关(当行为定,列不定时,无法使用push_back vector(因为push vector是同时增加行列,但是行非null,可能源代码中有相关判断)(push_back int可以);一维没有这个问题,不定长时能push_back)
创建方法:
正确操作:
#include<iostream>
#include<vector>
#define count 3
using namespace std;
//目标就是完成二维vector的所有操作
int main(void)
{
vector<vector<int>> vec1(count) ; //二维数组的 vector 定义
//初始化一个3x3的矩阵,数值为 333
for(int i = 0 ;i < vec1.size() ;++i){
for(int j= 0 ;j < count ;++j){
vec1[i].push_back(333);
}
}
//增加一行,数值为444
vector<int> temp ;
vec1.push_back(temp);
std::cout << "初始化行数"<<vec1.size()<<' '<<"列数:"<<vec1[0].size()<<endl;
int pos = vec1.size() - 1;
vec1[pos].push_back(444);
vec1[pos].push_back(444);
vec1[pos].push_back(444);
//增加一列
pos = vec1.size() ;
for(int i = 0 ;i < pos ;++i )
vec1[i].push_back(555);
//打印“二维数组”
for(int i = 0; i < vec1.size() ;++i){
for(int j = 0 ;j< vec1[0].size();++j){
cout << vec1[i][j] << " ";
}
cout << endl ;
}
}
1.定行列:可以下标直接赋值,也能push_back(增加列)
#include <iostream>
#include<vector>
#include<iomanip>
using namespace std;
int main()
{
int i, j;
int m=3,n=4;//m指行数,n指列数
std::cout << "请输入行数"<<m<<' '<<"列数:"<<n<<endl;
//注意下面这一行:vector<int后两个">"之间要有空格!否则会被认为是重载">>"
vector<vector<int> >vecInt(m, vector<int>(n));//m行n列
// std::cout << "初始化行数"<<vecInt.size()<<' '<<"列数:"<<vecInt[0].size()<<endl;
vector<int> vecRec(5,4);
vecInt.push_back(vecRec);//此时行数加1,变为m+1行,n列
cout<<vecInt.size()<<vecInt[0].size()<<endl;
//输出二维数组
for (i = 0; i < vecInt.size(); i++)
{
for (j = 0; j < vecInt[0].size(); j++)
{
cout<< vecInt[i][j];
}
cout << endl;
}
return 0;
}
2.定行:列数为empty,需要对列进行resize后才能使用(resize前(因为为null?)不能直接push_back vector?因为此时初始化包含了行,而新增的vector包含了行和列,但是push_back只是增加了行,并没有增加列,所以列没有增加进去,只增加了行)
int numRows=10,zone=5;//层数,每层需要的空间
vector<vector<int> > vec(numRows, vector<int>());//初始层数,赋值
std::cout << "初始化" << vec.empty() <<vec[0].empty()<< endl;//此时,行不为空,列为空
//或者 vector<int> > vec(numRows);
for (int i = 0; i < numRows; i++) {
vec[i].resize(zone);
}
3.都不定:为空,此时可以使用push_back vector!(因为行列都为null,同时增加了)需要用vector来push_back添加
#include <iostream>
#include<vector>
#include<iomanip>
using namespace std;
int main()
{
int i, j;
int m=3,n=4;//m指行数,n指列数
std::cout << "请输入行数"<<m<<' '<<"列数:"<<n<<endl;
//注意下面这一行:vector<int后两个">"之间要有空格!否则会被认为是重载">>"
vector<vector<int> >vecInt;//m行n列
std::cout << "初始化" << vecInt.empty() << endl;//此时为empty
vector<int> vecRec(5,4);
vecInt.push_back(vecRec);
cout<<vecInt.size()<<vecInt[0].size()<<endl;
//输出二维数组中的每个元素
for (i = 0; i < vecInt.size(); i++)
{
for (j = 0; j < vecInt[0].size(); j++)
{
cout<< vecInt[i][j];
}
cout << endl;
}
return 0;
}
使用vector<vector<int>> 时如果声明时不初始化,会报空指针引用错误:reference binding to null pointer of type 'value_type'。
根据《C++ primer第五版》P40:
默认初始化:
如果是内置类型的变量未被显示初始化,它的值由定义的位置决定。定义于任何函数体之外的变量被初始化为0。一种例外情况是,定义在函数体内部的内置类型变量将不被初始化。一个未被初始化的内置类型变量的值是未定义的,如果试图拷贝或者其他形式访问此类型将引发错误。
std::string初始化及判断为空
https://blog.csdn.net/wangshubo1989/article/details/50155093
1.不能用NULL初始化,可以用null进行判断
重要的是 std::string不能与null进行比较!!(但实际代码可以?是新特性?)
那么判断一个std::string 为空
std::string test_string;
std::string test_string_empty = "";
// std::string test_string_null = NULL; //此时构造函数把NULL当作char*了,不行?
if (test_string == "")
{
std::cout << "test_string is empty!" << std::endl;
}
if (test_string_empty.empty())
{
std::cout << "test_string_empty is empty!" << std::endl;
}
if (test_string_empty.length() == 0)
{
std::cout << "test_string_empty is empty!" << std::endl;
}