如何写出优质的C++代码:(六)“传值”和“传引用”该如何选择

在我们写一个函数接口的时候,我们使用什么方法来进行参数传递呢?是“传值”还是“传引用”?两者会对我们程序的执行呈现出截然不同的结果。

void func(const ExampleClass& exp);    //传引用
void func(ExampleClass exp);           //传值

从执行效率来讲,传引用要优于传值,原因在于,在传值的时候,程序会调用传参类型的构造函数,而传引用却不会。除此之外,其对于程序执行的结果影响也是很明显的,看看以下代码:

//基类
class CBase
{
    ......
	virtual void func1();
};

void CBase::func1()
{
	std::cout << "CBase::func1" << std::endl;
}

//派生类
class CSon1 : public CBase
{
    ......
	virtual void func1();
};
void CSon1::func1() 
{
	cout << "CSon1::func1" << endl;
}

void hostFunc(CBase exp)
{
    exp.func1();
}

int main() 
{

    CSon1 son1;
    hostFunc(son1);

    return 0;
}

执行这一段程序,会输出:

CBase::func1

这个输出结果不是我们所需要的,我们希望看到CSon1::func1被执行,但其实没有。另外,从上述的代码中,我们可以看出,CSon1的拷贝构造函数会被调用,对于hostFunc函数而言,此次参数传递的成本是:一次CSon1构造函数的调用,一次CSon1析构函数的调用。看起来这样的开销不算大,但是当CSon1中的成员变量比较多的时候,里面所有的成员变量都会被构造一次,其开销就会明显变多。

有什么方法可以避免这么多的构造函数被调用呢?......”传引用“可以解决这个问题,对于上面的hostFunc函数,可以这样写:

void hostFunc(const CBase& exp)
{
    exp.func1();
}

这种传递方式效率要高很多,没有任何构造函数和析构函数被调用。而且,也避免了CSon1功能被切割的问题(当一个派生类对象被以传值的方式传递并被视为其基类对象,基类的拷贝构造函数会被调用,而此时派生类的一些特有功能会被切割掉),此时,程序的执行结果为:

CSon1::func1

这正是我们希望看到的,程序执行了派生类的特有功能(CSon1::func1())。

有的程序员可能会想到通过指针传参也可以达到同样的目的,这种推测是正确的。比如这样:

void hostFunc(const CBase* exp)
{
    exp->func1();
}

其执行的结果同上。如果我们查看C++编译器的底层实现代码,会发现,引用本质上还是通过指针来实现的,使用传引用与传指针实际上是一样的。

综上所述,在程序中,我们尽量使用传引用来代替传值,前者效率高且可以有效避免切个问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值