恋爱38℃bl恋爱暴君百度云资源源

君,已阅读到文档的结尾了呢~~
c__3.0_语言定义文档,c语言定义数组,c语言自定义函数,c语言宏定义,c语言结构体定义,c语言函数定义,c语言 指针定义,c语言定义二维数组,c语言如何定义数组,c语言定义全局变量
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
c__3.0_语言定义文档
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口结构体类型数据作为函数参数(三种方法)
字体:[ ] 类型:转载 时间:
将一个结构体中变量中的数据传递给另一个函数,有以下三种方法。需要的朋友可以过来参考下,希望对大家有所帮助
(1)用结构体变量名作为参数。 代码如下:#include&iostream&#include&string&struct Student{&& };int main(){&S&void Print(Student one);&one.name="千手";&one.score=99;&Print(one);&cout&&one.name&&&cout&&one.score&&//验证 score的值是否加一了 &return 0;}void Print(Student one){&cout&&one.name&&&cout&&++one.score&&//在Print函数中,对score进行加一 }这种方式值采取的“值传递”的方式,将结构体变量所占的内存单元的内存全部顺序传递给形参。在函数调用期间形参也要占用内存单元。这种传递方式在空间和实践上开销较大,如果结构体的规模很大时,开销是很客观的。
并且,由于采用值传递的方式,如果在函数被执行期间改变了形参的值,该值不能反映到主调函数中的对应的实参,这往往不能满足使用要求。因此一般较少使用这种方法。
(2)用指向结构体变量的指针作为函数参数 代码如下:#include&iostream&#include&string&struct Student{&& };int main(){&S&void Print(Student *p);&one.name="千手";&one.score=99;&Student *p=& &Print(p);&cout&&one.name&&&cout&&one.score&&//验证 score的值是否加一了 &return 0;}void Print(Student *p){&cout&&p-&name&&&cout&&++p-&score&&//在Print函数中,对score进行加一 }这种方式虽然也是值传递的方式,但是这次传递的值却是指针。通过改变指针指向的结构体变量的值,可以间接改变实参的值。并且,在调用函数期间,仅仅建立了一个指针变量,大大的减小了系统的开销。
(3)用接头体变量的引用变量作函数参数 代码如下:#include&iostream&#include&string&struct Student{&& };int main(){&S&void Print(Student &one);&one.name="千手";&one.score=99;&Print(one);&cout&&one.name&&&cout&&one.score&&//验证 score的值是否加一了 &return 0;}void Print(Student &one){&cout&&one.name&&&cout&&++one.score&&//在Print函数中,对score进行加一 }实参是结构体变量,形参是对应的结构体类型的引用,虚实结合时传递的是地址,因而执行效率比较高。而且,与指针作为函数参数相比较,它看起来更加直观易懂。
因而,引用变量作为函数参数,它可以提高效率,而且保持程序良好的可读性。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具一、为什么需要traits编程技术
& & & &前面说了很多关于traits的光荣事迹,但是却一直没有介绍traits究竟是个什么东西,究竟是用来干什么的?traits在英文解释中就是特性,下面将会引入traits技术的作用,一步一步地揭开其神秘的面纱。
1.1 内嵌类型声明
1.1.1 以迭代器所指对象的类型声明局部变量
& & & &下面是一个以迭代器为模板形参的函数模板:
template&typename&Iterator&&&
void&func(Iterator&iter)&&
template&typename Iterator&
void func(Iterator iter)
& & & &假如现在算法中需要声明一个变量,而变量的类型是迭代器所指对象的类型,应该怎么处理呢?
template&typename&Iterator&&&
void&func(Iterator&iter)&&
&&&&*Iterator&
template&typename Iterator&
void func(Iterator iter)
*I//这样定义变量可以吗?
& & & &上面的代码是不可以通过编译的,虽然C++支持sizeof(),但是并不支持typeof(),就算是用到RTTI性质中的typeid(),获取到的也仅仅是类型的名字,因此不能直接用来声明变量。此时可以利用函数模板的参数类型推导机制解决问题,例如:
template&typename&Iterator,&typename&T&&&
void&func_impl(Iterator&iter,&T&t)&&
template&typename&Iterator&&&
void&func(Iterator&iter)&&
&&&&func_impl(iter,&*iter);
int&main(int&argc,&const&char&*argv[])&&
&&&&int&i;&&
&&&&func(&i);&&
template&typename Iterator, typename T&
void func_impl(Iterator iter, T t)
T//这里就解决了问题
//这里做原本func()的工作
template&typename Iterator&
void func(Iterator iter)
func_impl(iter, *iter);//func的工作全部都移到func_impl里面了
int main(int argc, const char *argv[])
& & & &函数func作为对外接口,实际的操作却由函数func_impl执行,通过函数func_impl的参数类型推导,获取到Iterator指向对象的类型T,从而解决了问题。
1.1.2&以迭代器所指对象的类型声明返回类型
& & & &现在通过函数模板的参数类型推导解决了函数体内声明变量的问题,但问题又来了,如果需要返回类型是迭代器所指对象的类型又可以怎样做呢?
template&typename&Iterator&&&
(*Iterator)&func(Iterator&iter)&&
template&typename Iterator&
(*Iterator) func(Iterator iter)
//这样定义返回类型可以吗?
& & & &在这种情况下,模板的参数类型推导机制也无能为力了,因为它只能推导参数,并不能推导函数的返回类型。STL解决这种问题的办法就是内嵌类型声明,即在迭代器内部添加一种&特性&,通过这种&特性&,算法可以很容易地获知迭代器所指对象的类型,请看下面的代码:
template&typename&T&&&
class&Iterator&&
&&&&typedef&T&value_
&&&&Iterator(T&*p&=&0)&:&m_ptr(p)&{}&&
&&&&T&&operator*()&const&{&return&*m_}&&
private:&&
&&&&T&*m_&&
template&typename&Iterator&&&
typename&Iterator::value_type&&
func(Iterator&iter)&&
&&&&return&*&&
int&main(int&argc,&const&char&*argv[])&&
&&&&Iterator&int&&iter(new&int(10));&&
&&&&cout&&func(iter)&&&&
template&typename T&
class Iterator
typedef T value_//内嵌类型声明
Iterator(T *p = 0) : m_ptr(p) {}
T& operator*() const { return *m_}
template&typename Iterator&
typename Iterator::value_type
//以迭代器所指对象的类型作为返回类型,长度有点吓人!!!
func(Iterator iter)
int main(int argc, const char *argv[])
Iterator&int& iter(new int(10));
cout&&func(iter)&&
//输出:10
& & & &函数func()的返回类型前面必须加上关键词typename,原因在本人之前写的&C++模板学习&中也解释过,因为T是一个template参数,编译器在编译实例化func之前,对T一无所知,就是说,编译器并不知道Iterator&T&::value_type是一个类型,或者是一个静态成员函数,还是一个静态数据成员,关键词typename的作用在于告诉编译器这是一个类型,这样才能顺利通过编译。
1.2 原生指针也是一种迭代器
& & & &之前在介绍迭代器的分类之时说过,原生指针也是一种迭代器,此时问题就来了,原生指针并不是一种类类型,它是无法定义内嵌类型的。因此,上面的内嵌类型实现还不能完全解决问题,那可不可以针对原生指针做特殊化的处理呢?答案是肯定的,利用模板偏特化就可以做到了。
& & & &《泛型思维》一书对模板偏特化的定义是:
& & & &&针对template参数更进一步的条件限制所设计出来的一个特化版本。
template&typename&T&&&
//这个泛型版本允许T为任何类型
template&typename T&
& & & &我们很容易接受上面的类模板有一个形式如下的偏特化版本:
template&typename&T&&&
class&C&T*&&&&
template&typename T&
class C&T*&
& & & &这个特化版本仅适用于T为原生指针的情况,&T为原生指针&就是&T为任何类型&的一个更进一步的条件限制。那如何利用模板偏特化解决原生指针不能内嵌类型的问题呢?下面介绍的iterator_traits就是关键了。
二、迭代器萃取机--iterator_traits
2.1 原生指针并不是一种类类型
& & & &STL里面使用iterator_traits这个结构来专门&萃取&迭代器的特性,前面代码中提到的value_type就是迭代器的特性之一:
template&typename&Iterator&&&
struct&iterator_traits&&
&&&&typedef&typename&Iterator::value_type&value_&&
template&typename Iterator&
struct iterator_traits
typedef typename Iterator::value_type value_
& & & &如果Iterator有定义value_type,那么通过iterator_traits作用之后,得到的value_type就是Iterator::value_type,比较之前写的版本和经iterator_traits作用后的版本:
template&typename&Iterator&&&
typename&Iterator::value_type&&
func(Iterator&iter)&&
&&&&return&*&&
template&typename&Iterator&&&
typename&iterator_traits&Iterator&::value_type&&
func(Iterator&iter)&&
&&&&return&*&&
template&typename Iterator&
typename Iterator::value_type
//这行是返回类型
func(Iterator iter)
//通过iterator_traits作用后的版本
template&typename Iterator&
typename iterator_traits&Iterator&::value_type
//这行是返回类型
func(Iterator iter)
& & & &从长度上看,好像需要敲的代码更多了,为什么要这么麻烦加上一层间接层呢?由于原生指针也是一种迭代器,而且不是一种类类型,因此原生指针并不能定义内嵌类型。这里通过实现iterator_traits的一个偏特化版本就可以解决这个问题了,具体的实现如下:
template&typename&T&&&
struct&iterator_traits&T*&&&
&&&&typedef&T&value_&&
//iterator_traits的偏特化版本,针对迭代器是个原生指针的情况
template&typename T&
struct iterator_traits&T*&
typedef T value_
& & & &大家在进行函数重载的时候,应该都曾遇到过以下的情况:
void&func(int&*ptr)&&
void&func(const&int&*ptr)&&
//函数版本一
void func(int *ptr)
//函数版本二
void func(const int *ptr)
& & & &以上两个函数虽然函数、形参个数和位置都一样,但它们不是同一个函数,而是函数重载的一种情况,也就是说函数形参的const和非const版本是不一样的,在函数版本一里面,可以修改指针ptr指向的数据,但是在函数版本二里面却不可以,因为传入的指针ptr是一个const指针。由此可以联想到,当将一个const指针作为模板形参传给前面声明的偏特化版本的iterator_traits会有发生什么情况呢?
iterator_traits&const&int*&::value_type&&
iterator_traits&const int*&::value_type
//获得的value_type是const int,并不是int
& & & &当我们想用iterator_traits萃取出value_type并声明一个临时变量时,却发现声明的变量是const类型,并不能进行赋值,这违背了我们的用意。我们需要一种方法区别const和非const才能避免这种误会的发生,答案很简单,只要另外再设计一个iterator_traits偏特化版本就可以了:
template&typename&T&&&
struct&iterator_traits&const&T*&&&
&&&&typedef&T&value_&&
template&typename T&
struct iterator_traits&const T*&
typedef T value_
& & & &现在,不论是自定义的迭代器,还是原生指针int*或者是const int*,都可以通过iterator_traits获取到正确的value_type。
2.2 iterator_traits中定义的类型
& & & &STL根据经验,定义了迭代器最常用到的五种类型:value_type、difference_type、pointer、reference、iterator_category,任何开发者如果想将自己开发的容器与STL结合在一起,就一定要为自己开发的容器的迭代器定义这五种类型,这样都可以通过统一接口iterator_traits萃取出相应的类型,下面列出STL中iterator_traits的完整定义:
tempalte&typename&I&&&
struct&iterator_traits&&
&&&&typedef&typename&I::iterator_category&iterator_&&
&&&&typedef&typename&I::value_type&value_&&
&&&&typedef&typeanme&I:difference_type&difference_&&
&&&&typedef&typename&I::pointer&&&
&&&&typedef&typename&I::reference&&&
tempalte&typename I&
struct iterator_traits
typedef typename I::iterator_category iterator_
typedef typename I::value_type value_
typedef typeanme I:difference_type difference_
typedef typename I::
typedef typename I::
& & & &下面会分别介绍一下这五种类型:
(1) 迭代器类型之一:value_type& & & &value_type就是指迭代器所指对象的类型,例如,原生指针也是一种迭代器,对于原生指针int*,int即为指针所指对象的类型,也就是所谓的value_type。
(2) 迭代器类型之二:difference_type& & & &difference_type用来表示两个迭代器之间的距离,例如:
int&array[5]&=&{1,&2,&3,&4,&5};&&
int&*ptr1&=&array&+&1;
int&*ptr2&=&array&+&3;
ptrdiff_t&distance&=&ptr2&-&ptr1;
int array[5] = {1, 2, 3, 4, 5};
int *ptr1 = array + 1;//指向2
int *ptr2 = array + 3;//指向4
ptrdiff_t distance = ptr2 - ptr1;//结果即为difference_type
& & & &上面代码中,指针ptr2与ptr1相减的结果的类型就是difference_type,对于原生指针,STL以C++内建的ptrdiff_t作为原生指针的difference_type。
(3) 迭代器类型之三:reference_type
& & & &reference_type是指迭代器所指对象的类型的引用,reference_type一般用在迭代器的*运算符重载上,如果value_type是T,那么对应的reference_type就是T&;如果value_type是const T,那么对应的reference_type就是const T&。
(4) 迭代器类型之四:pointer
& & & &pointer就是指迭代器所指的对象,也就是相应的指针,对于指针来说,最常用的功能就是operator*和operator-&两个运算符。因此,迭代器需要对这两个运算符进行相应的重载工作:
T&&operator*()&const&{&return&*&}&
T*&operator-&()&const&{&return&&}&
T& operator*() const { return * } // T& is reference type
T* operator-&() const { } // T* is pointer type
(5) 迭代器类型之五:iterator_category
& & & &iterator_category的作用是标识迭代器的移动特性和可以对迭代器执行的操作,从iterator_category上,可将迭代器分为Input&Iterator、Output&Iterator、Forward&Iterator、Bidirectional&Iterator、Random Access&Iterator五类,具体为什么要这样分类,简单来说,就是为了尽可能地提高效率,这也是STL的宗旨之一。具体的情况已经在本人的&《STL源码剖析》学习之迭代器&中详细介绍过,这里就不在多说了。
2.3 iterator_traits完整定义
& & & &为了保证iterator_traits可以正常工作,STL提供了一个iterator类,所有自定义的迭代器都必须继承自它,这样才能保证这些自定义的迭代器可以顺利地狱其它STL组件进行协作,iterator类具体定义如下:
template&typename&Category,&&
&&&&&&&&&typename&T,&&
&&&&&&&&&typename&Distance&=&ptrdiff_t,&&
&&&&&&&&&typename&Pointer&=&T*,&&
&&&&&&&&&typename&Reference&=&T&&&&
struct&iterator&&
&&&&typedef&Category&iterator_&&
&&&&typedef&T&value_&&
&&&&typedef&Distance&difference_&&
&&&&typedef&Pointer&&&
&&&&typedef&Reference&&&
template&typename Category,
typename T,
typename Distance = ptrdiff_t,
typename Pointer = T*,
typename Reference = T&&
struct iterator
typedef Category iterator_
typedef T value_
typedef Distance difference_
& & & &类iterator不包含任何成员变量,只有类型的定义,因此不会增加额外的负担。由于后面三个类型都有默认值,在继承它的时候,只需要提供前两个参数就可以了,如:
template&&typename&T&&&
class&ListIter&:&public&std::iterator&std::forward_iterator_tag,&T&&&
阅读(...) 评论()在调用函数时候,引用形参和普通型参是有着很大的区别。
首先看函数在使用普通型参时候,编译器是怎么工作的。在函数调用的时候,编译器为被调函数在栈空间申请一块内存,此时普通形参也在这块内存取,被实参初始化。说到这里就明白了,在被调函数执行完毕后,编译器会将其弹出栈空间。因此,形参也就消失了,此时主函数的实参没有改变。
引用,在C++中,是一个变量的别名。因此可以通过引用去改变被因引用变量的值。其实,在底层引用的实现就是通过保存被引用变量的地址实现的,但是在语言层面它又不同于指针(不像指针的含义一样,如此接近机器)。因此在调用函数使用引用传值时候,实际传入的就是变量的地址。因此,可以通过引用取改变实参。引用其实可以这样理解,它即实现了对变量的地址的访问(类似于指针),然而看起来它却和变量本身没有差别。
在编写先序建立二叉树的时候,若使用普通的变量,则会出错。因为在递归调用
CreateBiTree(T-&lchild);的时候,若传入普通变量,则不会改变T-&lchild的值,因此也就不会产生树的其他节点。因此,引用的作用显而易见。
void CreateBiTree(BiTree &T)
scanf(&%c&,&ch);
if(ch=='#')T=NULL;
if(!(T = (BiTNode *)malloc(sizeof(BiTNode))))
CreateBiTree(T-&lchild);
CreateBiTree(T-&rchild);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:4950次
排名:千里之外
原创:12篇
(2)(7)(1)(1)(2)(3)(2)

我要回帖

更多关于 今天的恋爱百度云资源 的文章

 

随机推荐