【总结】STL 坑汇总

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;
    }

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值