快捷搜索:   服务器  安全  linux 安全  MYSQL  dedecms

完整的学习C++的读书路线图(5)(2)

Cout<<iter->second<<endl;

}

Pair<map<int, string>::iterator, map<int, string>::iterator> mapPair;

mapPair = mapStudent.equal_range(2);

if(mapPair.first == mapPair.second)
{

cout<<”Do not Find”<<endl;

}

Else

{

Cout<<”Find”<<endl;
}

mapPair = mapStudent.equal_range(3);

if(mapPair.first == mapPair.second)
{

cout<<”Do not Find”<<endl;

}

Else

{

Cout<<”Find”<<endl;
}

}

    6. 数据的清空与判空

    清空map中的数据可以用clear()函数,判定map中是否有数据可以用empty()函数,它返回true则说明是空map

    7. 数据的删除

    这里要用到erase函数,它有三个重载了的函数,下面在例子中详细说明它们的用法

 #include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

Map<int, string> mapStudent;

mapStudent.insert(pair<int, string>(1, “student_one”));

mapStudent.insert(pair<int, string>(2, “student_two”));

mapStudent.insert(pair<int, string>(3, “student_three”));

//如果你要演示输出效果,请选择以下的一种,你看到的效果会比较好

//如果要删除1,用迭代器删除

map<int, string>::iterator iter;

iter = mapStudent.find(1);

mapStudent.erase(iter);

//如果要删除1,用关键字删除

Int n = mapStudent.erase(1);//如果删除了会返回1,否则返回0

//用迭代器,成片的删除

//一下代码把整个map清空

mapStudent.earse(mapStudent.begin(), mapStudent.end());

//成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合

//自个加上遍历代码,打印输出吧

}

    8. 其他一些函数用法

    这里有swap,key_comp,value_comp,get_allocator等函数,感觉到这些函数在编程用的不是很多,略过不表,有兴趣的话可以自个研究

    9. 排序

    这里要讲的是一点比较高深的用法了,排序问题,STL中默认是采用小于号来排序的,以上代码在排序上是不存在任何问题的,因为上面的关键字是int型,它本身支持小于号运算,在一些特殊情况,比如关键字是一个结构体,涉及到排序就会出现问题,因为它没有小于号操作,insert等函数在编译的时候过不去,下面给出两个方法解决这个问题

    第一种:小于号重载,程序举例

 #include <map>

#include <string>

Using namespace std;

Typedef struct tagStudentInfo

{

Int nID;

String strName;

}StudentInfo, *PStudentInfo; //学生信息

Int main()

{

int nSize;

//用学生信息映射分数

map<StudentInfo, int>mapStudent;

map<StudentInfo, int>::iterator iter;
StudentInfo studentInfo;

studentInfo.nID = 1;

studentInfo.strName = “student_one”;

mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));

studentInfo.nID = 2;

studentInfo.strName = “student_two”;

mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));

for (iter=mapStudent.begin(); iter!=mapStudent.end(); iter++)

cout<<iter->first.nID<<endl<<iter->first.strName<<endl<<iter->second<<endl;

}

    以上程序是无法编译通过的,只要重载小于号,就OK了,如下:

 Typedef struct tagStudentInfo

{

Int nID;

String strName;

Bool operator < (tagStudentInfo const& _A) const

{

//这个函数指定排序策略,按nID排序,如果nID相等的话,按strName排序

If(nID < _A.nID) return true;

If(nID == _A.nID) return strName.compare(_A.strName) < 0;

Return false;

}

}StudentInfo, *PStudentInfo; //学生信息

第二种:仿函数的应用,这个时候结构体中没有直接的小于号重载,程序说明

#include <map>

#include <string>

Using namespace std;

Typedef struct tagStudentInfo

{

Int nID;

String strName;

}StudentInfo, *PStudentInfo; //学生信息

Classs sort

{

Public:

Bool operator() (StudentInfo const &_A, StudentInfo const &_B) const

{

If(_A.nID < _B.nID) return true;

If(_A.nID == _B.nID) return _A.strName.compare(_B.strName) < 0;

Return false;

}

};

Int main()

{

//用学生信息映射分数

Map<StudentInfo, int, sort>mapStudent;

StudentInfo studentInfo;

studentInfo.nID = 1;

studentInfo.strName = “student_one”;

mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));

studentInfo.nID = 2;

studentInfo.strName = “student_two”;

mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));

}

    10. 另外

    由于STL是一个统一的整体,map的很多用法都和STL中其它的东西结合在一起,比如在排序上,这里默认用的是小于号,即less<>,如果要从大到小排序呢,这里涉及到的东西很多,在此无法一一加以说明。

    还要说明的是,map中由于它内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,如果用map函数可以实现的功能,而STL Algorithm也可以完成该功能,建议用map自带函数,效率高一些。

    下面说下,map在空间上的特性,否则,估计你用起来会有时候表现的比较郁闷,由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节的,一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子),我想大家应该知道,这些地方很费内存了吧,不说了……

    */

    /*深入理解sizeof

    最近在论坛里总有人问关于sizeof的问题,并且本人对这个问题也一直没有得到很好的解决,索性今天对它来个较为详细的总结,同时结合strlen进行比较,如果能对大家有点点帮助,这是我最大的欣慰了。

    一、好首先看看sizeof和strlen在MSDN上的定义:

    首先看一MSDN上如何对sizeof进行定义的:

 sizeof Operator
sizeof expression
The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type
(including aggregate types). This keyword returns a value of type size_t.
The expression is either an identifier or a type-cast expression (a type specifier
enclosed in parentheses).
When applied to a structure type or variable, sizeof returns the actual size, which may include
padding bytes inserted for alignment. When applied to a statically dimensioned array, sizeof
returns the size of the entire array. The sizeof operator cannot return the size of dynamically
allocated arrays or external arrays.
  然后再看一下对strlen是如何定义的:

strlen
Get the length of a string.
Routine Required Header:
strlen <string.h>
size_t strlen( const char *string );
Parameter
string:Null-terminated string
Libraries
All versions of the C run-time libraries.
Return Value
Each of these functions returns the number of characters in string, excluding the terminal
NULL. No return value is reserved to indicate an error.
Remarks
Each of these functions returns the number of characters in string, not including the
terminating null character. wcslen is a wide-character version of strlen; the argument of
wcslen is a wide-character string. wcslen and strlen behave identically otherwise.

    二、由几个例子说开去。

    第一个例子:

 char* ss = "0123456789";
    sizeof(ss) 结果 4 ===》ss是指向字符串常量的字符指针

    sizeof(*ss) 结果 1 ===》*ss是第一个字符

    char ss[] = "0123456789";

    sizeof(ss) 结果 11 ===》ss是数组,计算到\\\\\\\\\\\\\\\\0位置,因此是10+1

    sizeof(*ss) 结果 1 ===》*ss是第一个字符

    char ss[100] = "0123456789";

    sizeof(ss) 结果是100 ===》ss表示在内存中的大小 100×1

    strlen(ss) 结果是10 ===》strlen是个函数内部实现是用一个循环计算到\\\\\\\\\\\\\\\\0为止之前

    int ss[100] = "0123456789";

    sizeof(ss) 结果 400 ===》ss表示再内存中的大小 100×4

    strlen(ss) 错误 ===》strlen的参数只能是char* 且必须是以\\\\\\\\\\\\\\\'\\\\\\\\\\\\\\\'结尾的

    char q[]="abc";

    char p[]="a\\\\\\\\\\\\\\\\n";

    sizeof(q),sizeof(p),strlen(q),strlen(p);

    结果是 4 3 3 2

    第二个例子:
 class X
{
int i;
int j;
char k;
};
X x;
cout<<sizeof(X)<<endl; 结果 12 ===》内存补齐
cout<<sizeof(x)<<endl; 结果 12 同上

    第三个例子:

    char szPath[MAX_PATH]

    如果在函数内这样定义,那么sizeof(szPath)将会是MAX_PATH,但是将szPath作为虚参声明时(void fun(char szPath[MAX_PATH])),sizeof(szPath)却会是4(指针大小)

    三、sizeof深入理解。

    1.sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小。

    2.sizeof是算符,strlen是函数。

    3.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以\\\\\\\\\\\\\\\'\\\\\\\\\\\\\\\'\\\\\\\\\\\\\\\\0\\\\\\\\\\\\\\\'\\\\\\\\\\\\\\\'结尾的。sizeof还可以用函数做参数,比如:

    short f();

    printf("%d\\\\\\\\\\\\\\\\n", sizeof(f()));

    输出的结果是sizeof(short),即2.

    4.数组做sizeof的参数不退化,传递给strlen就退化为指针了。

    5.大部分编译程序 在编译的时候就把sizeof计算过了 是类型或是变量的长度这就是sizeof(x)可以用来定义数组维数的原因

    char str[20]="0123456789";

    int a=strlen(str); //a=10;

    int b=sizeof(str); //而b=20;

    6.strlen的结果要在运行的时候才能计算出来,时用来计算字符串的长度,不是类型占内存的大小。

    7.sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。

    8.当适用了于一个结构类型时或变量, sizeof 返回实际的大小, 当适用一静态地空间数组, sizeof 归还全部数组的尺 寸。 sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸

    9.数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如:

    fun(char [8])

    fun(char [])

    都等价于 fun(char *) 在C++里传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小如果想在函数内知道数组的大小, 需要这样做:进入函数后用memcpy拷贝出来,长度由另一个形参传进去

    fun(unsiged char *p1, int len)

    {

    unsigned char* buf = new unsigned char[len+1]

    memcpy(buf, p1, len);

    }

    有关内容见: C++ PRIMER?

    10.计算结构变量的大小就必须讨论数据对齐问题。为了CPU存取的速度最快(这同CPU取数操作有关,详细的介绍可以参考一些计算机原理方面的书),C++在处理数据时经常把结构变量中的成员的大小按照4或8的倍数计算,这就叫数据对齐(data alignment)。这样做可能会浪费一些内存,但理论上速度快了。当然这样的设置会在读写一些别的应用程序生成的数据文件或交换数据时带来不便。MS VC++中的对齐设定,有时候sizeof得到的与实际不等。一般在VC++中加上#pragma pack(n)的设定即可。或者如果要按字节存储,而不进行数据对齐,可以在Options对话框中修改Advanced compiler页中的Data alignment为按字节对齐。

    11.sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。如sizeof(max)若此时变量max定义为int max(),sizeof(char_v) 若此时char_v定义为char char_v [MAX]且MAX未知,sizeof(void)都不是正确形式

    四、结束语

    sizeof使用场合。

    1.sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。例如:

    void *malloc(size_t size),

    size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)。

    2.用它可以看看一类型的对象在内存中所占的单元字节。

    void * memset(void * s,int c,sizeof(s))

    3.在动态分配一对象时,可以让系统知道要分配多少内存。

    4.便于一些类型的扩充,在windows中就有很多结构内型就有一个专用的字段是用来放该类型的字节大小。

    5.由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用sizeof来代替常量计算。

    6.如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。

    */

顶(0)
踩(0)

您可能还会对下面的文章感兴趣:

最新评论