终于来到了第三章,然而这一章第一二节看了就很让人劝退。。。很多细节书里没提导致我必须猜测或搜索才能让书里的代码运行起来。
指针的算术运算
- 所谓指针的算术运算,举个例子,可以是
*(array+2);
假设array所存储的元素类型为int,array+2就是array的地址(也是array首元素的地址)+array所存储的元素类型所占大小*2。换句话说,
array所存储元素类型是int型,首元素地址假设存在1000,那么array+2就是1000+2x4(假设int所占字节大小为4字节)即1008,这个答案就是指针算术答案。还有,下面的find()函数中输入进的实参也相当于指针算术运算。 - array可以是一个指针,他作为形参的时候,函数里也可以用下标运算符来进行操作,比如
返回类型 函数名(int *array;int value......){//...if(array[i]==value){//...}}
学过C的同学知道,可以对指针使用下标运算符在任何情况,本人在此默认我,和同学们知道,就不详细说了。 - 我搬一个书上的代码吧,我通过代码给大家说明一些东西。
#include<iostream>
#include<vector>
using namespace std;
template<typename elemType>
inline elemType* begin(vector<elemType>&vec)
{
return vec.empty()?0:&vec[0];
}
template<typename elemType>
inline elemType* end(vector<elemType>&vec)
{
return vec.empty()?0:&vec[4];//注意,这里要返回vector最后元素的下一个地址,因为你只用作和指针指向的地址比较,
//而不进行读写操作(若读写则是非法操作,因为vec[4]已越界)!
}
template<typename elemType>elemType* find(elemType *first,const elemType *last,const elemType &value)//原来第一个参数最前面有const
//编译器不会通过的会报错不可把const elemType(在这里int,double或者string)*类型对象返回(转换,下同)给elemType*类型对象,所以去掉const即可,
//所以在返回对象的时候其类型如果没有const则不要返回给带const的对象!(也就是const类型对象不可以返回给非const类型对象,不过
//非const类型对象可以返回给const类型对象,const对象也不可返回给const对象,记下!
{
if(!first||!last)
{
return 0;
}
//first和last比,如果不等,first++,指向容器(数组)中下一个元素,相等则返回first;或者如果first所指元素和value等,则返回first
for(;first!=last;++first)
{
if(*first==value)
{
return first;
}
}
return 0;//走到这里证明没找到和value一样的元素
}
int main()
{
string sa[4]={"pooh","piglet","eeyore","tigger"};
vector<string>svec(sa,sa+4);
if(!svec.empty())
{
const string *ps=find(begin(svec),end(svec),svec[3]);
cout<<*ps<<endl;
}
return 0;
}
代码解说:
template<typename elemType>
inline elemType* begin(vector<elemType>&vec)
{
return vec.empty()?0:&vec[0];
}
template<typename elemType>
inline elemType* end(vector<elemType>&vec)
{
return vec.empty()?0:&vec[4];//注意,这里要返回vector最后元素
//的下一个地址,因为你只用作和指针指向的地址比较,
//而不进行读写操作(若读写则是非法操作,因为vec[4]已越界)!
}
这是模板函数的使用,同时这是个小函数,咱们用inline函数即可。然后这个函数体也很简洁,可以借鉴学习,.empty()函数是判断vector对象是不是个空的vector。注意,这里是返回相应的地址,因为你其他函数调用这两个函数,其他函数的指针变量跟这两个函数返回的地址是要比较的,其他的看一下注释写的吧。
template<typename elemType>elemType* find(elemType *first,const elemType *last,const elemType &value)//原来第一个参数最前面有const
//编译器不会通过的会报错不可把const elemType
//(在这里int,double或者string)*类型对象返回(转换,下同)给
//elemType*类型对象,所以去掉const即可,
//所以在返回对象的时候其类型如果没有const则不要返回给带const的对象!
//(也就是const类型对象不可以返回给非const类型对象,不过
//非const类型对象可以返回给const类型对象,
//const对象也不可返回给const对象,记下!
{
if(!first||!last)
{
return 0;
}
//first和last比,如果不等,first++,指向容器(数组)中下一个元素,
//相等则返回first;或者如果first所指元素和value等,则返回first
for(;first!=last;++first)
{
if(*first==value)
{
return first;
}
}
return 0;//走到这里证明没找到和value一样的元素
}
这便是重要函数了
template<typename elemType>elemType* find(elemType *first,const elemType *last,const elemType &value){...}
注意这个函数的定义,咱们是定义的一个函数模板,因为你传进来的vector的元素类型可能是int,double,float,或者string,char等类型。这不就灵活了吗对不对?
然后就涉及到指针的算术运算和比较了,比如++first;就是指针的算术运算,让first指针指向vector下一个元素。
还有const类型和非const类型的传递关系(不管是形参实参间传递),还是返回类型的传递,亦或变量间传递,都要记住非const类型对象可以返回给const类型对象,const类型对象不可以返回给非const类型对象,const对象也不可返回给const对象(codeblocks IDE是这样)
其他程序执行过程看下注释就OK
int main()
{
string sa[4]={"pooh","piglet","eeyore","tigger"};
vector<string>svec(sa,sa+4);
if(!svec.empty())
{
const string *ps=find(begin(svec),end(svec),svec[3]);
cout<<*ps<<endl;
}
return 0;
}
主函数在此,咱们定义了一个array(你认为是数组也行),然后array传变量给vector<string>
型的对象。然后注意!要判空!,先确定vector对象不为空,再去执行find函数!
然后find函数里return first或者return 0给ps指针,然后提领ps指针,把内容显示到屏幕中,OK,结束程序。
注意:const string *ps=find(begin(svec),end(svec),"tigger");
你还不能把svec[3]改成字符串常量。这是错误写法,编译器报错
错误:没有匹配函数调用’find(std:: cxx11::basic_string*, std::
cxx11::basic_string*, const char [7])’|
注意:vec[4]下标里别写vec.end()+1,编译器报错
return vec.empty()?0:&vec[vec.end()+1];//错误写法
return vec.empty()?0:&vec[4];//注意,这里要返回vector最后元素的下一个地址,因为你只用作和指针指向的地址比较,
//而不进行读写操作(若读写则是非法操作,因为vec[4]已越界)!
错误写法的报错信息:
cpp|12|error: no match for ‘operator[]’(操作数类型为’std::vector >‘和’ gnu_cxx:: normal_iterator*, std::vector > >’)|
附上程序运行结果图:
再看一个例子:
#include<iostream>
using namespace std;
template<typename elemType>elemType* find(elemType *first,const elemType *last,const elemType &value)//原来第一个参数最前面有const
//编译器不会通过的会报错不可把const elemType
//(在这里int,double或者string)*类型对象返回(转换,下同)给
//elemType*类型对象,所以去掉const即可,
//所以在返回对象的时候其类型如果没有const则不要返回给带const的对象!
//(也就是const类型对象不可以返回给非const类型对象,不过
//非const类型对象可以返回给const类型对象,const对象也不可返回给const对象,记下!
{
if(!first||!last)
{
return 0;
}
//first和last比,如果不等,first++,指向容器(数组)中下一个元素,相等则返回first;或者如果first所指元素和value等,则返回first
for(;first!=last;++first)
{
if(*first==value)
{
return first;
}
}
return 0;//走到这里证明没找到和value一样的元素
}
int main()
{
int ia[8]={1,1,2,3,5,8,13,21};
double da[6]={1.5,2.0,2.5,3.0,3.5,4.0};
string sa[4]={"pooh","piglet","eeyore","tigger"};
int *pi=find(ia,ia+8,ia[3]);
double *pd=find(da,da+6,da[3]);
string *ps=find(sa,sa+4,sa[3]);
cout<<*pi<<endl;
cout<<*pd<<endl;
cout<<*ps<<endl;
return 0;
}
这个就是针对array类型的了。这个程序的缺点就是你只能查询array里有的,没有的不能查询,,,,程序会RE。
附一张程序运行结果图:
两程序均0错误0警告