C++ vector容器和sort函数的学习

五迷三道 提交于 2019-12-02 04:58:53

Vector注意事项:

  1. 声明形如vector<> vec;的不是new出来而是作为普通变量的那么不需要delete, 在变量超出作用域时会自动回收
  2. 如果是用*vec = new vector<>()这种方式动态创建的vector那么需要delete vec
  3. vec里存放的元素如果不是指针那么不用delete, 这些元素在vec被释放时会被一起释放
  4. vec里存放的元素是指针并且这些指针都是指向自己new的对象的话, 那么需要自己一个个delete

c++中内存拷贝函数(C++ memcpy)详解

头文件:C++:#include<cstring>
原型:void*memcpy(void*dest, const void*src,unsigned int count); //参数是void 
功能:由src所指内存区域复制count个字节到dest所指内存区域。  
说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。
函数原型:
void *memcpy(void*dest, const void *src, size_t n);
功能:
由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。
头文件:
#include<string.h>
返回值:
  函数返回一个指向dest的指针。
说明:
  1.source和destin所指内存区域不能重叠,函数返回指向destin的指针。
  2.strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。
memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;
例:
  char a[100], b[50];
  memcpy(b, a,sizeof(b)); //注意如用sizeof(a),会造成b的内存地址溢出。
  strcpy就只能拷贝字符串了,它遇到'\0'就结束拷贝;例:
  char a[100], b[50];
strcpy(a,b);
  3.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。
  //注意,source和destin都不一定是数组,任意的可读写的空间均可。

strcpy和memcpy的区别


strcpymemcpy都是标准C库函数,它们有下面的特点。

strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。

已知strcpy函数的原型是:char* strcpy(char* dest, const char* src);

memcpy提供了一般内存的复制。即memcpy对于需要复制的内容没有限制,因此用途更广。

void *memcpy( void *dest, const void *src, size_t count );

char * strcpy(char * dest, const char * src) // 实现src到dest的复制
{
  if ((src == NULL) || (dest == NULL)) //判断参数src和dest的有效性
  {

      return NULL;
  }
  char *strdest = dest;        //保存目标字符串的首地址
  while ((*strDest++ = *strSrc++)!='\0'); //把src字符串的内容复制到dest下
  return strdest;
}
void *memcpy(void *memTo, const void *memFrom, size_t size)
{
  if((memTo == NULL) || (memFrom == NULL)) //memTo和memFrom必须有效
         return NULL;
  char *tempFrom = (char *)memFrom;             //保存memFrom首地址
  char *tempTo = (char *)memTo;                  //保存memTo首地址      
  while(size -- > 0)                //循环size次,复制memFrom的值到memTo中
         *tempTo++ = *tempFrom++ ;  
  return memTo;
}
strcpymemcpy主要有以下3方面的区别。

1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
一、函数说明

1memcpy函数

void  *memcpy(void *s1,  const void *s2,  size_t  n);

说明:

函数memcpy从s2指向的对象中复制n个字符到s1指向的对象中。如果复制发生在两个重叠的对象中,则这种行为未定义。

返回值:

函数memcpy返回s1的值。

2strcpy函数

char  *strcpy(char *s2, const char *s1);

说明:

函数strcpy把s1指向的串(包括空字符)复制到s2指向的数组中。如果复制发生在两个重叠的对象中,则这种行为未定义。

返回值:

函数strcpy返回s2的值。

3strncpy函数

char  *strncpy(char *s2, const char *s1, size_t n);

说明:

函数strncpy从s1指向的数组中最多复制n个字符(不复制空字符后面的字符)到s2指向的数组中。如果复制发生在两个重叠的对象中,则这种行为未定义。

如果s1指向的数组是一个比n短的字符串,则在s2定义的数组后面补空字符,直到写入了n个字符。

返回值:

函数strncpy返回s2的值。

二、注意事项

strcpy 是依据 “\0” 作为结束判断的,如果 s2 的空间不够,则会引起 buffer overflow。

memcpy用来在内存中复制数据,由于字符串是以“\0”结尾的,所以对于在数据中包含“\0”的数据只能用memcpy。

Strncpy和memcpy很相似,只不过它在一个终止的空字符处停止。当n>strlen(s1)时,给s2不够数的空间里填充“\0”;当n<=strlen(s1)时,s2是没有结束符“\0”的。

这里隐藏了一个事实,就是s2指向的内存一定会被写n个字符。

所以总的来说注意:

1、s2指向的空间要足够拷贝;使用strcpy时,s2指向的空间要大于等于s1指向的空间;使用strncpymemcpy时,s2指向的空间要大于或等于n。

2、使用strncpymemcpy时,n应该大于strlen(s1),或者说最好n >= strlen(s1)+1;这个1 就是最后的“\0”。

3、使用strncpy时,确保s2的最后一个字符是“\0

动态创建和删除二维数组

其实在刷题的时候用全局数组才是最快的

//动态开辟二维数组
    int** p = new int*[rows];//开辟m行
    for (size_t i = 0; i < rows; i++)
    {
        p[i] = new int[cols];
    }
    //初始化值
    for (int i = 0; i <rows; i++)
        for (int j = 0; j < cols; j++)
             p[i][j]=0; 
   //删除的时候
   for(int i=0;i<rows;i+=){
     delete[] p[i];
    }
   delete[] p

【debug】vs2013中定义的全局变量count在使用时提示:“不明确的符号”

  今天用vs2013编写程序时遇到以下这么一个bug
  提示错误信息:count:不明确的符号,,count明明定义为全局变量,怎么成为不明确的符号了呢??百思不得其解
  查阅资料找到了答案:命名空间std有一个count函数
  编译器不知道调用的是:std::count(),还是用户定义的全局变量count,故报错
  解决办法,在count前面加上作用域标识符:::count即可
  如果同时要用到std中的count函数,加上命名空间和作用标识符即可:std::count()

C++中的sort函数使用自定义比较函数的具体运行过程是怎么样的呢?(sort函数是qsort的改进版,以后就用sort就好咯)

  首先,sort不会用到冒泡排序,时间复杂度过高导致性能太差。SGI STL版本的sort在数据量很大时采用Quick Sort进行分段递归排序。如果分段之后的数据量小于某个门槛值,会改用Insertion Sort这种在数据量很小时性能很好的排序算法。
  其次,sort接受一个用户指定的函数,要求:对于排序后的每两个相邻元素都要满足使cmp结果为TRUE。也就是说,在进行比较运算的时候拿用户定义的比较函数来替代原有的比较运算符。
  所以具体实现就是:在快排分割成的小子序列中进行插入排序。

  具体的例子 sort()
  类似于快排:O(nlogn) 头文件为#include
  使用方法:Sort(start,end,排序方法)

Sort函数有三个参数:
(1)第一个是要排序的数组的起始地址。
(2)第二个是结束的地址(最后一位要排序的地址)
(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。
例一:sort函数没有第三个参数,实现的是从小到大

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
 int a[10]={9,6,3,8,5,2,7,4,1,0};
 for(int i=0;i<10;i++)
 cout<<a[i]<<endl;
sort(a,a+10);
 for(int i=0;i<10;i++)
 cout<<a[i]<<endl;
 return 0;
}
例二
通过上面的例子,会产生疑问:要实现从大到小的排序肿么办?
 这就如前文所说需要在sort()函数里的第三个参数里做文章了,告诉程序我要从大到小排序!
需要加入一个比较函数 complare(),此函数的实现过程是这样的
bool complare(int a,int b)
{
 return a>b;
}
这就是告诉程序要实现从大到小的排序的方法!
#include<iostream>
#include<algorithm>
using namespace std;
bool complare(int a,int b)
{
 return a>b;
}
int main()
{
 int a[10]={9,6,3,8,5,2,7,4,1,0};
 for(int i=0;i<10;i++)
 cout<<a[i]<<endl;
 sort(a,a+10,complare);//在这里就不需要对complare函数传入参数了,//这是规则
 for(int i=0;i<10;i++)
 cout<<a[i]<<endl;
 return 0;
}
例三:
通过上面例一、二的方法虽然实现了从大到小和从大到小的排序,这样做还是有点麻烦,因为还需要自己编写告诉程序执行何种排序的原则的函数,c++标准库强大的功能完全可以解决这种麻烦。
Sort函数的第三个参数可以用这样的语句告诉程序你所采用的排序原则
less<数据类型>()//从小到大排序
greater<数据类型>()//从大到小排序
结合本例子,这样的就可以完成你想要的任何一种排序原则了
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
 int a[10]={9,6,3,8,5,2,7,4,1,0};
 for(int i=0;i<10;i++)
 cout<<a[i]<<endl;
sort(a,a+10,less<int>());
 for(int i=0;i<10;i++)
 cout<<a[i]<<endl;
 return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
 int a[10]={9,6,3,8,5,2,7,4,1,0};
 for(int i=0;i<10;i++)
 cout<<a[i]<<endl;
 sort(a,a+10,greater<int>());
 for(int i=0;i<10;i++)
 cout<<a[i]<<endl;
 return 0;
}
例四:利用sort函数还可以实现对字符的排序,排序方法大同小异,下面就把程序范例展示一下
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
 char a[11]="asdfghjklk";
 for(int i=0;i<10;i++)
 cout<<a[i]<<endl;
 sort(a,a+10,greater<char>());
 for(int i=0;i<10;i++)
 cout<<a[i]<<endl;
 return 0;
}




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!