条款20和条款21

简介: 条款20和条款21

条款20:宁以pass-by-reference-to-const替换pass-by-value

在c语言中我们知道,函数传参时,直接传参会发生拷贝行为。因此,为了减少拷贝,我们通常会传引用。同样,这个规则在c++中也适用。同时c++中有类的概念,当我们传一个类类型的参数时,如果这个类较大,传值无疑会产生大量多余的拷贝行为,因此,可以通过传const引用的形式传参。

来看一个例子:

class Base {
public:
  Base() {
    cout << "Base constructor" << endl;
  }
  ~Base() {
    cout << "Base destructor" << endl;
  }
  Base(const Base &) {
    cout << "Base copy destructor" << endl;
  }
  void output () const {
    cout << "Base output" << endl;
  }
};
void output(Base base) {
  base.output();
}
int main() {
  Base base;
  cout << "=============" << endl;
  output(base);
  return 0;
}

当使用直接传值时输出:

Base constructor
=============
Base copy destructor
Base output
Base destructor
Base destructor

可以发现确实发生了一次拷贝行为。

而如果采用传引用的形式:

void output(const Base &base) {
  base.output();
}

程序输出:

Base constructor
=============
Base output
Base destructor

发现没有确实没有发生拷贝行为。

同时,传引用还可以避免对象切割问题。来看下面这个例子:

class Window {
public:
  virtual void show() const;
};
class WindowWithButton : public Window{
public:
  virtual void show() const override;
};
void Window::show() const {
  cout << "window show" << endl;
}
void WindowWithButton::show() const {
  cout << "window with button show" << endl;
}
void func(Window w) {
  w.show();
}
int main() {
  WindowWithButton windowWithButton;
  func(windowWithButton);
  return 0;
}

WindowWithButton类继承自Window类。func函数接受一个Window类型的值,当我们传入一个WindowWithButton类型的实参时,期望的应该是调用WindowWithButton类的show方法,而程序输出:

window show

这正是因为参数是值传递的原因,当使用引用传递时:

void func(const Window &w) {
  w.show();
}

程序输出:

window with button show

引用书中一段话

如果窥视C++编译器的底层,你会发现,references往往以指针实现出来,因此pass by reference通常意味真正传递的是指针。因此如果你有个对象属于内置类型(例如int),pass by value往往比pass by reference的效率高些。对于内置类型而言,当你有机会选择采用pass-by-value或pass-by-reference-to-const时,选择pass-by-value并非没有道理。这个忠告也适用于STL的迭代器和函数对象,因为习惯上它们都被设计为passd by value。

条款21:必须返回对象时,别妄想返回其reference

当我们发现了值传递和引用传递的优劣时,恨不得什么情形下都使用引用,但有些情况下需要注意。函数中我们不能返回局部变量的引用或指针,因为当函数结束时,局部变量也会自动销毁,此时再返回它的引用或指针是未定义的行为,不要这样做。

同时,返回new出来的对象时,我们也没办法保证调用者会正确的析构该内存,因此会造成内存泄漏。

因此,有时为了保证正确性,我们不得不返回一个对象。

当你必须在“返回一个reference和返回一个object之间抉择时,你的工作就是挑出行为正确的那个。”

相关文章
|
6月前
|
缓存 编译器 C++
条款23和条款24
条款23和条款24
|
5月前
软件著作权申请流程及费用_快速登记_软著材料及常见问题解答FAQ
阿里云软件著作权申请涉及账号注册、实名认证和选择服务。在阿里云官网注册账号,通过实名认证后,选择登记服务,如普通359.1元/件或加急1080元/件。在线填报申请表,阿里云初审后授权提交,打印申请表并邮寄材料。版权中心审查后,通过则领取证书,未通过需补正。整个过程约20天。详细步骤见阿里云百科相关教程。
202 3
|
6月前
|
安全
AIGC知识产权赔偿条款
【2月更文挑战第9天】AIGC知识产权赔偿条款
55 3
AIGC知识产权赔偿条款
|
6月前
|
编译器 C++
条款5和条款16
条款5和条款16
|
6月前
|
编译器 C++
条款6和条款7
条款6和条款7
|
6月前
|
C++
条款10和条款13
条款10和条款13
|
6月前
条款9和条款22
条款9和条款22
为什么注册商标还要申请版权登记?
本文将与您探讨注册商标后申请版权登记的好处
315 0
为什么注册商标还要申请版权登记?
商标驳回|不规范汉字禁止作为商标注册和使用
很多客户为了迎合自己销售产品的用途,绞尽脑汁去变动一些成语或者修改一些字的笔画来避开审查员的近似审核,这些小聪明,往往适得其反
855 0
|
小程序
阿里云软件著作权普通登记和加急有什么区别?
阿里云软件著作权登记普通等级价格便宜359/件,需要全程用户自助操作,阿里云仅通过初审,适合不着急并有软著申请经验的用户;加急登记有专属助手提供在线答疑,价格较贵1080元/件,审查周期是20-30工作日;顾问登记全程有阿里云专业顾问提供整理和填报材料服务,提高通过率,适合没有经验毕竟着急的用户,顾问登记是阿里云百科比较推荐的;安心登记价格最贵,相对于顾问登记支持补正不通过可退全款,用户完全没有风险
368 0
阿里云软件著作权普通登记和加急有什么区别?