Effective C++条款20:宁以pass-by-reference-to-const替换pass-by-value
条款20:宁以pass-by-reference-to-const替换pass-by-value
以下考虑类对象:
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;
};
//类的调用
bool validateStudent(Student s);
Student plato;
bool platoIsOK = validateStudent(plato);
上述类的调用中,在以传值得方式在进行参数传递,在上述使用中,由于是值传递,student 会进行拷贝构造,会调用一次Person和一次Student中的构造函数,由于string也是一个类,在student和person中各有两个string类,也就是说会调用四次string的构造函数,加起来一共会调用六次构造函数,同理,同时会调用六次析构函数。
当我们使用引用传参(pass-by-reference-to-const)
bool validateStudent(const Student& s);
这是,不会调用student的拷贝构造函数,也就不会有上述中的多次构造、析构函数的调用,这样就有效地提高了效率。
对象切割:当把一个派生类对象 pass-by-value 给一个基类对象时,会发生对象切割。
例子如下:
class Window
{
public:
//...
std::string name() const;
virtual void display() const;
};
class WindowWithScrollBars:public Window
{
public:
//...
virtual void display() const;
}
void printNameAndDisplay(Window w)
{
std::cout<<w.name();
w.display();
}
//调用函数
WindowWithScrollBars wwsb;
printNameAndDisplay(wwsb);
printNameAndDisplay() 函数中,我们pass-by-value时,对象就可能会被切割,函数会将其视为一个Window对象,而不是WindowWithScrollBars 对象,它所有作为WindowWithScrollBars 对象的特性都会被切除(忽视),这就是对象切割。
但是通过pass-by-reference-to-const就可以很有效地解决问题。
代码如下:
void printNameAndDisplay(const Window& w)
{
std::cout<<w.name();
w.display();
}
//调用函数
WindowWithScrollBars wwsb;
printNameAndDisplay(wwsb);
但是,当对象属于内置类型时,pass-by-value通常比pass-by-reference-to-const的效率要高,STL的迭代器和函数对象,都使用了pass-by-value.
要记住的点:
1、尽量以pass-by-reference-to-const替换pass-by-value。通常前者比较高效,并可避免对象的切割问题(slicing problem)
2、以上规则并不适用于内置类型,以及STL的迭代器和函数对象。对他们而言,pass-by-value往往比较适当
posted on 2022-08-13 16:15 DylanYeung 阅读(26) 评论(0) 编辑 收藏 举报