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

原创文章,转载请注明出处。

----------------------------------------------------------------------------

引言:

----------------------------------------------------------------------------

       在传递函数参数时,为了减少拷贝构造的成本,我们经常会传递指针。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);

void func(float& f);

 

// func.cpp

float f = 0.f;

func(&f);

func(f);

----------------------------------------------------------------------------

       从上述代码可以看出,在使用指针传递对象时,我们可以明确的知道正在传送一个地址,而按引用传递时时虽然非常方便,因为看起来像是对原始对象操作一样,但是我们并不能从代码中看出这是在传递对象的地址。

       我们再来看一段代码:

代码清单:

----------------------------------------------------------------------------

// myclass.h

class CMyClass{

};

 

CMyClass& getObject () {

       CMyClass mc;

       return mc;

}

----------------------------------------------------------------------------

       大家能看出有什么问题吗?

       答对了。getObject()接口应该返回一个对象的引用,而在上面的代码中却返回了一个临时对象的引用,这是很危险的。编译器会报错:

warning C4172: 返回局部变量或临时变量的地址: 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

int getValueAndMove2Next(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著

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

女儿叫老白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值