关闭

关于 pass-by-reference-to-const 和 pass-by-value

标签: 读书笔记c++博客
344人阅读 评论(0) 收藏 举报

第一次写博客,其实算一个读书笔记吧,我觉得记一下可能能增加我得印象,废话不说,直接正题。

这次记一个很小的问题, effective c++ 中 的条款20是:宁以pass-by-reference-to-const替换pass-by-value( 宁愿按const引用传递来替代按值传递),按值传递就是函数参数都是以实际实参的复件(副本)为初值,而调用端所获得的是函数返回值的一个复件,这些复件系由对象的copy构造函数产出,这可能使得pass-bu-value成为昂贵的(费时的)操作,下面是书中的源码:

<span style="font-size:18px;">class Person
{
 public:
  Person();
  ~virtual Person();
   ...
  private:
  std::string name;
  std::string address;
};
class Student: public Person {
public:
  Student();
  ~Student();
  ...
private:
  std::string schoolName;
  std::string schoolAddress;
};</span>

现在考虑如下代码:


bool validateStudent ( Student s ); 

Student plato;

bool platoIsOK = validateStudent(plato);

这显然是按值传递,它将会以plato为蓝本将s初始化,这将会调用Student的copy构造函数,当validateStudent返回时s将会被销毁(析构函数),所以按值传递的成本是“Student的一次拷贝函数的调用加上一次析构函数的调用”。


除此之外,Student对象还有两个string对象,所以每次构造一个Student对象就构造了两个string对象,此外! Student对象继承自Person对象,所以构造Student对象前又会构造一个Person对象, 而Person对象又有两个string对象。。。。,所以,总的计算下来,按值传递一个Student对象会导致”六次构造函数和六次析构函数的调用
!“(看起来很多的样子)。


然而,如果我们使用pass by reference-to-const (const引用): //前面讲过,用const修饰参数是一个很好的习惯,所以尽量使用const

bool validateStudent (const Student& s ) ;

这种传递方式效率会高很多,因为没有任何的构造函数或析构函数会被调用(没有任何新对象被创建),用const修饰是重要的,这将确保传入的Student不会被修改。


此外,按引用传递还有一个好处,就是能避免slicing(对象切割)问题,(什么鬼), 当一个子类class对象以by value方式传递并被视为一个父类对象,父类的copy构造函数会被调用,而”造成此对象行为像个子类对象“的哪些特化性质全被切割掉了,仅仅留下I一个父类对象”,现在看下面代码

<span style="font-size:18px;">class Window {
public:
  ...
  std::string name() const;  //返回窗口名称
  virtual void display() const; //显示窗口及其内容
}

class WindowWithScrollBare: public window {
 public:
   ...
   virtual void display() const;
};</span>


假设你希望写个函数打印窗口名称,然后显示该窗口,下面是错误的示范

<span style="font-size:18px;">void printNameAndDisplay( Window w )   //不正确,参数可能被切割
{
  std::cout<<w.name();
  w.display();
}</span>

当我们给它传递一个WindowWithScrollBare对象时,

WindowWithScrollBare wwsb;

printNameAndDisplay(wwsb);

参数w会被构造成Window对象而不是WindowWithScrollBare对象,而wwsb的所有特化信息会被全部切除,在printNameAndDisplay函数内不论传递过来的对象是什么类型,

参数w就像一个window对象(因为他的类型是window)。 因此在printNameAndDisplay内调用display调用的总是Window::display,绝不会是WindowWithScrollBare.Display.


解决切割(slicing)的办法就是pass by reference-to-const

<span style="font-size:18px;">void printNameAndDisplay( const Window& w )   //不正确,参数可能被切割
{
  std::cout<<w.name();
  w.display();
}</span>

这样,传进来的窗口是什么类型,w就表现出那种类型



请记住:

1.尽量以pass-by-reference-to-const替换pass-by-value。前者通常比较高效,并且可避免切割问题。

2.以上规则并不适用于内置类型,以及STL的迭代器和函数对象。对它们而言,pass-by-value往往比较合适。



0
0
查看评论

(小结)pass-by-reference-to-const替换pass-by-value

在effective c++中条款20说到,要以常量引用的方式替代传值传参。 主要是三个原因: 传值可能造成slicing(对象切割)的问题。 传值可能浪费了一大堆内存构造新的对象。 对象的传值还要调用copy构造函数(如果设计的好就没了),都是开销啊。 书中的建议:内
  • QQ276592716
  • QQ276592716
  • 2011-08-03 17:52
  • 356

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

条款20:宁以pass-by-reference-to-const替换pass-by-value        (Prefer pass-by-reference-to-const to pass-by-value.)内容:...
  • scofieldzhu
  • scofieldzhu
  • 2009-06-17 11:17
  • 1100

Effective C++ 20. Prefer pass-by-reference-to-const to pass-by-value

Prefer pass-by-reference-to-const to pass-by-value
  • ruihuank
  • ruihuank
  • 2017-10-22 20:28
  • 50

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

条款20:宁以pass-by-reference-to-const替换pass-by-value
  • hualicuan
  • hualicuan
  • 2014-05-30 09:17
  • 643

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

总结: 1、尽量以pass-by-reference-to-const替换pass-by-value。前者更高效且可以避免切断问题。 2、这条规则并不适用于内建类型及STL中的迭代器和函数对象类型。对于它们,pass-by-value通常更合适。    ...
  • u013074465
  • u013074465
  • 2015-03-12 20:27
  • 1026

尽量用pass-by-reference-to-const(const引用)替换pass-by-value(传值)

1、尽量以pass-by-reference-to-const替换pass-by-value,前者通常毕竟高校,并可避免切割问题(slicing problem)。 2、以上规则并不适用于内置规则,以及STL的迭代器和函数对象。对它们而言,pass-by-value往往比较适当。
  • zyq522376829
  • zyq522376829
  • 2015-09-01 20:40
  • 786

effective c++:宁以pass-by-reference-to-const替代pass-by-value

class People { public: People() { cout << " construct fun " << endl; } People(const People& i) :...
  • c337134154
  • c337134154
  • 2015-10-31 00:42
  • 417

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

(一) 调用函数的时候如果传递参数pass-by-value,那么函数参数都是以实际实参的副本为初值,调用端所获得的亦是函数返回值的一个复件。 看下面代码: class Person { public: Person(); virtual ~Person(); pri...
  • u010470972
  • u010470972
  • 2014-06-15 14:19
  • 733

Effective C++ 第20条:宁以pass-by-reference-to-const替换pass-by-value

第20条:宁以pass-by-reference-to-const替换pass-by-value        缺省情况下C++ 以byvalue方式(一个继承自C 的方式)传递对象至(或来自)函数。除非你另外指定,否则函数参数都是以实际实参的复件(副本)为...
  • caoshangpa
  • caoshangpa
  • 2018-02-01 11:06
  • 59

Effective C++ Item 20 宁以pass-by-reference-to-const替换pass-by-value

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie
  • zhsenl
  • zhsenl
  • 2014-05-26 15:26
  • 526
    个人资料
    • 访问:57678次
    • 积分:1578
    • 等级:
    • 排名:千里之外
    • 原创:99篇
    • 转载:47篇
    • 译文:0篇
    • 评论:4条
    最新评论