笨木头  2014-11-18 21:10     其它     阅读(6595)     评论(14)
转载请注明,原文地址: http://www.benmutou.com/archives/1928
文章来源:笨木头与游戏开发
 

还记得之前说过,函数的参数用指针,可以避免拷贝产生额外的开销吗?

这次要来介绍一个类似的参数,那就是引用参数。

 

 
笨木头花心贡献,啥?花心?不呢,是用心~

转载请注明,原文地址:http://www.benmutou.com/archives/1928

文章来源:笨木头与游戏开发
 

 

1.什么是引用?

对于初学者来说,引用和取地址值操作可能会有点犯迷糊。
[cce_cpp]
int num = 10;

int *p = # // 这是取地址操作 int &yinyong = num; // 这是引用

[/cce_cpp]
引用可以理解为“别名”,粗俗地说,就是“外号”,代码中就是把yinyong这个变量作为num的外号。

以后yinyong就是num,num就是yinyong,给yinyong赋值,那么,num的值也会改变,因为它们是一样的。

 

这类似指针的*p。

 

2.用引用作为函数参数

引用的主要用途是作为函数的参数,至于原因,晚点再说,先看看怎么用:
[cce_cpp]
// 函数定义
void version1(string &s)
{
}

// 调用方式 string str = "hehe"; version1(str); [/cce_cpp]
从代码里就可以发现了,参数前面使用&符号,就是引用参数了,而参数的传递却不需要改变,我们不需要特意创建一个str的别名,然后再传递给函数。

直接把str传递进去就可以了。

 

这个时候,在version1函数里,可以改变str的值,因为这是引用,str就是s,s就是str,改变任何一个的值,另一个值也会被改变的。

 

3.使用引用作为参数的好处?

为什么要用引用做参数?在参数前面加个&瞬间就变复杂了,不过,它还是有好处的。

那就是——不需要拷贝。

比如刚刚的代码,如果不使用引用的话,就要拷贝一次str的值,version1里的s就是拷贝的值。

使用引用之后,str就是s,s就是str,不存在拷贝的操作,可以节省内存和时间。

 

等等,这和指针怎么这么像?

是的,和指针很像,所以,什么时候用引用做参数,什么时候用指针做参数,也是很容易让人迷惑的。

 

这个迷惑的问题,等会再讨论。

 

4.又是const

如果在引用参数前面加上const,又会是什么情况呢?

这将会变得很复杂,复杂的同时又很强大。

比如:
[cce_cpp]
// 这样一个函数
void version1(string &s)
{
}

// 这样使用是允许的 string str = "nihao"; version1(str);

// 这样使用是不允许的 version1("nihao"); [/cce_cpp]
因为字符串常量"nihao"默认是const char*类型,和函数指定的参数类型不一致,所以不能这么使用。

但是加上const就不一样了:
[cce_cpp]
// 使用了const
void version2(const string &s)
{
}

// 这次可以这么使用了 version2("nihao"); [/cce_cpp]
给引用参数加上const的好处就是:

1.如果实参的类型不正确,但是能够转换为正确的类型,那么,就会生成一个临时变量,这个临时变量就是转换后的正确类型。

2.如果实参的类型正确,但是,它不是左值,此时也会生成一个临时变量,作为参数使用。

 

第一条好处就是刚刚代码里的情况了,const char*是可以转换为string的,所以这次会自动生成一个string临时变量(值是"nihao"),s参数就是这个临时变量的别名。

第二条是什么意思呢?比如我们的函数是void version(int &num);  但调用的时候这么调用:version(888);

888类型是int,但明显不是左值,所以,这时也会生成一个int临时变量(值是888),num参数就是这个临时变量的别名。

 

为什么要这么麻烦的规则?

因为有时候不希望传递参数的时候要执行拷贝操作,所以要用引用参数。

但使用引用参数,就代表可以随意修改,并且会影响原来的值,这有时候不太安全。

所以就在引用参数前面加上const,这样,既不需要拷贝,也不能修改,两全其美。

 

而使用const后的两条规则,是为了可以更方便地使用函数,如果没有这样的规则,那么,很多时候都会报错。

比如使用version(888)会报错、使用version2("nihao")也报错,这会烦死人的。

 

5.什么时候用引用参数,什么时候用指针参数?

这是一个不好回答的问题,一不小心可能就误导大家了。

大家记住引用的几个特点:

1.某个变量一旦作为另一个变量的引用(别名),就永远是那个变量的引用,不能换。这和指针不一样,指针变量随时可以指向其它的地址。

2.引用变量一定不会是空值的,比如int &yinyong = num;    yinyong就是一个引用变量,它一定要初始化,不能这样:int &yinyong; 会报错的。所以引用变量一定不会是空值,这和指针变量不一样,指针变量是可以不初始化的(但这样很危险)。

3.在引用参数前面加上const,就拥有那两条规则,在很多时候会很方便。

 

于是,上面是引用的一些特点,当能够使用引用参数的时候,就使用引用参数,如果无法使用,或者使用起来很奇怪,那就选择使用指针参数。

这是基本的判断规则。

 

但,这么说肯定还是很模糊的,大家感兴趣的,可以百度一下“什么时候用引用参数,什么时候用指针参数?”,会找到很多讨论的话题。

都看一看,然后心中有个底,慢慢地就会清楚了。

 

6.结束

看我发文章的速度越来越慢,就知道我快要坚持不住了。

继续,Fight.....(小若:所以说,为什么最后要用省略号,用感叹号不是比较有干劲么?)

 

 

 

 
14 条评论
  • 我爱纪录片app 2014-12-03 19:27:22

    好久没来了,一看,笨木头好久都没更新了
    0回复
    • 博主 糟糕_树叶的mut 2014-12-03 20:11:33

      遇到个棘手项目,得全力以赴地接手,才能随心所欲地写文章
      0回复
      • 我爱纪录片app 2014-12-03 23:14:41

        遇到= =,不做独立开发啦?
        0回复
        • 博主 糟糕_树叶的mut 2014-12-04 08:06:04

          找了个扫厕所的工作,私底下偷偷写游戏
          0回复
          • 我爱纪录片app 2014-12-05 09:21:06

            看来靠自己还是养不活自己,唉。。。
            0回复
            • 笨木头,懒得登录 2014-12-05 12:14:41

              其实是以前大学老师找我,做项目...PS:能养活自己,养不活一个家
              0回复
              • 我爱纪录片app 2014-12-05 13:29:11

                啊啊啊~木小受要成家了啊
                0回复
                • 博主 糟糕_树叶的mut 2014-12-05 21:13:32

                  总是误解我的意思
                  0回复
  • ffish 2014-12-01 18:14:08

    期待木头,讲讲继承、多态、虚函数这块的东西,还有加油!
    0回复
    • 博主 糟糕_树叶的mut 2014-12-01 21:07:14

      谢谢
      0回复
  • TTTT 2014-11-29 13:31:42

    希望博主有空更新,复习一遍还是有不少的收获的。
    0回复
    • 博主 糟糕_树叶的mut 2014-11-29 14:40:02

      等我能无压力驾驭新项目的时候,就开更了~
      0回复
  • 方奕昀 2014-11-23 18:21:51

    加油哈,我看到14章了
    0回复
    • 博主 糟糕_树叶的mut 2014-11-24 15:24:05

      谢谢,最近忙新项目了,估计要断更几个月
      0回复
发表评论
粤ICP备16043700号

本博客基于 BlazorAnt Design Blazor 开发