找回密码
 立即注册
收起左侧

C++老鸟日记035 引用与指针

1
回复
6426
查看
[复制链接]
累计签到:41 天
连续签到:1 天
来源: 原创 2018-9-28 18:09:51 显示全部楼层 |阅读模式

马上注册,查看详细内容!注册请先查看:注册须知

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 baizy77 于 2018-10-1 21:01 编辑

版权声明
---------------------------------------------------------------------------------------------------------------------
该文章原创于Qter开源社区(www.qter.org
作者: 女儿叫老白 (白振勇)
转载请注明出处!
---------------------------------------------------------------------------------------------------------------------
本套课程属于:《C++跨平台开发干货》系列课程。
-----------------------------------------------------------------------------

引言:
----------------------------------------------------------------------------
       在传递函数参数时,为了减少拷贝构造的成本,我们经常会传递指针。C++也提供了另外一种语法可以达到相同的功能:引用。那么引用有什么优点,关于引用我们该知道点啥呢?
正文:
----------------------------------------------------------------------------
我们先来看一段代码:
代码清单:
----------------------------------------------------------------------------
// myclass.h
class CMyClass {
public:
       int getValue() {return m_nValue;}
};

CMyClass mc;
CMyClass* pMc =&mc;
CMyClass& rMc= mc;

mc.getValue();
pMc->getValue();
rMc.getValue();
----------------------------------------------------------------------------
       从上述代码可以很明显的看出,使用指针与使用引用的相同点是都可以直接操作对象。相比较而言,使用引用比使用指针的代码,使我们的变量看起来更像对象,代码更清晰,可读性也更好了(因为不用写指针操作符->)。
       既然这样,我们是不是可以任意的使用引用呢?不是的。使用引用还要遵守几个规则:
       1, 引用被创建时必须初始化,指针可以在任何时候被初始化。
       2, 一个引用被初始化为指向一个对象后,就不能再改为指向另一个对象的引用。指针则可以指向其他合法对象。
       3, 引用不能指向NULL,必须确保引用跟合法的内存关联。(注1)
       而且,指针还有它自身的优点。
代码清单:
----------------------------------------------------------------------------
// func.h
void func(float*pFloat);
voidfunc(float& f);

// func.cpp
float f = 0.f;
func(&f);
func(f);
----------------------------------------------------------------------------
       从上述代码可以看出,在使用指针传递对象时,我们可以明确的知道正在传送一个地址,而按引用传递时时虽然非常方便,因为看起来像是对原始对象操作一样,但是我们并不能从代码中看出这是在传递对象的地址。
       我们再来看一段代码:
代码清单:
----------------------------------------------------------------------------
// myclass.h
class CMyClass{
};

CMyClass&getObject () {
       CMyClass mc;
       return mc;
}
----------------------------------------------------------------------------
       大家能看出有什么问题吗?
       答对了。getObject()接口应该返回一个对象的引用,而在上面的代码中却返回了一个临时对象的引用,这是很危险的。编译器会报错:
warningC4172: 返回局部变量或临时变量的地址: mc
       所以,一个返回值是引用类型的函数是不可以将临时变量作为返回值的。

还有写时候,我们需要向函数中传入一个指针,并且在函数中改变该指针的内容(比如自加操作),这时我们最好使用引用的方式传递参数:
代码清单:
----------------------------------------------------------------------------
// myclass.h
class CMyClass {
public:
    CMyClass() :m_nValue(0) {}
public:
    int getValue() { return 0;}
private:
    int m_nValue;
};


// code.cpp
int getValueAndMove2Next(CMyClass**pObj) {
    int val = 0;
    if ((NULL != pObj)&& (NULL != *pObj)) {
        val =(*pObj)->getValue();
        (*pObj)++;
    }
    return val;
}
void func() {
     CMyClass  arrayMC[4];
     CMyClass* pMc = arrayMC;
     for (int i=0; i<4; i++){
            getValueAndMove2Next(&pMc);
}
}
----------------------------------------------------------------------------
       上面的代码有点绕,getValueAndMove2Next()接口的功能是调用(*pObj)的getValue()接口,并将pObj移动指向下一个对象。可以看出代码不是很清晰。如果我们把这个接口改成下面的写法呢:
代码清单:
----------------------------------------------------------------------------
// code.cpp
intgetValueAndMove2Next(CMyClass*&pObj) {
    int val = 0;
    if (NULL != pObj)  {
        val = pObj->getValue();
        pObj++;
    }
    return val;
}
void func() {
    CMyClass arrayMC[4];
    CMyClass* pMc = arrayMC;
    for (int i = 0; i < 4; i++) {
        getValueAndMove2Next(pMc);
    }
}
----------------------------------------------------------------------------
       可以看出,把参数类型改为CMyClass*&(指针引用)之后,代码清晰多了。而且功能完全一样。

结语:
----------------------------------------------------------------------------
       从本文讨论的内容可以看出,指针和引用各自有各自的优点或者特点,我们应根据这些特点在合适的场合使用合适的语法,从而发挥出C++的最大价值。

  如果您喜欢本文欢迎转发。
参考资料
----------------------------------------------------------------------------
注1:《C++编程思想》两卷合订本中文版(P255-P257),(美) Bruce Eckel  Chuck Allison著


回复

使用道具 举报

累计签到:50 天
连续签到:1 天
2018-10-2 09:56:59 显示全部楼层
看了,还是写两个感受。   
引用必须赋值,不能赋空值,  引用的对象不能更改。
指针一看就明白,而引用感觉上是在操作对象,    但代码可读性好。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了