Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / C++ 之 值传递和引用传递

1  值传递  值传递实际上是,拷贝实参的值传递给形参,常用于“小对象” (small objects)int fact(int val) // factorial of val {int ret = 1;// assign ret * val to ret and decrement valwhile (val > 1)ret *= val--; return ret;}  调用该函数:cout << "5! is " << fact(5) << endl;  <Effective C++> 中提及,值传递适用的“小对象”为:内置类型(built-in types),STL迭代器,函数对象类型(function object types) 2  引用传递  引用传递不涉及拷贝,传递给形参的是实参变量的引用,常用来传递“大数值” (large values)  使用引用传递,有两个优点:更高效,防切断2.1  更高效  下面是 Person 基类,及其派生类 Student 的定义// class Person and its subclass Studentclass 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;};  现有一个验证学生身份的函数,形参为值传递,则拷贝实参给形参的代价是:调用基类 Person 的构造函数一次,基类内 string 型数据成员的构造函数两次,派生类 Student 的构造函数一次,派生类内 string 型数据成员两次,最后还会调用相应的析构函数六次,共计十二次调用,自然效率低下。  而使用引用传递,并不涉及拷贝操作,故而显著的提高了效率。// 1) pass-by-value bool validateStudent(Student s);// 2) pass-by-reference-to-const bool validateStudent(const Student& s);2.2  防切断  下面的例子中,派生类 WindowWithScrollBars 中,重写了基类 Window 的虚函数 display// base class Window
class Window{public: std::string name() const;// return name of windowvirtual void display() const;// draw window and contents};class WindowWithScrollBars : public Window {public:virtual void display() const;};  在 printNameAndDisplay 函数中,调用了 dispaly 函数,而形参若采用值传递方式,则会发生“切断” (slicing),即 wwsb 调用的是 Window::display()// pass-by-value is incorrectvoid printNameAndDisplay(Window w){std::cout << w.name();w.display();}// WindowWithScrollBars object will be sliced offWindowWithScrollBarswwsb;printNameAndDisplay(wwsb);  因为在 printNameAndDisplay 中,并不修改传递进来的参数。因此,可使用 pass-by-const-reference 的形式,避免“切断”的发生3  动态绑定  上面"切断"的例子,实际上涉及的是 C++ 的动态绑定机制 (dynamic binding), 而动态绑定的一个关键点就是引用传递,下面看个更形象的例子:class Quote {public:std::string isbn() const;virtual double net_price(std::size_t n) const;};// Bulk_quote inherits from Quoteclass Bulk_quote : public Quote { public:double net_price(std::size_t) const override;};   在 print_total 函数中,需要调用 net_price,采用 pass-by-const-reference 形式// calculate and print the pricedouble print_total(ostream &os, const Quote &item, size_t n){double ret = item.net_price(n);return ret;}  实际程序中,调用 Quote::net_price 还是 Bulk_quote::net_price 取决于传递进来的参数// basic is type Quote; bulk is type Bulk_quoteprint_total(cout, basic, 20); // calls Quote::net_priceprint_total(cout, bulk, 20); // calls Bulk_quote::net_price  C++ 的动态绑定机制,使得程序直到运行时,才基于引用或指针绑定的对象类型,来选择调用哪个虚函数小结:直接套用 <C++ Programming Language> 中的建议和 <C++ Primer> 中对动态绑定的解释1) use pass-by-value for small objects2) use pass-by-const-reference to pass large values that you don’t need to modify3) dynamic binding happens when a virtual function is called through a reference (or a pointer) to a base class 参考资料: <C++ Programming Language_4th> ch 12.2.1 <Effective C++_3rd> item 20 <C++ Primer_5th> ch 6.2,  ch 15.1本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-04/130421.htm