本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie
经验:尽量以pass-by-reference-to-const替代pass-by-value。前者通常比较高效,并可避免切割问题(slicing problem)
以上规则并不适用于内置类型,以及STL的迭代器和函数对象。对它们而言,pass-by-value往往比较适当。
示例:pass-by-value
#include <iostream>
#include <string>
using namespace std;
class Person{
public:
Person(){cout << "Person constructor" << endl;}
Person(const Person &){cout << "Person copy constructor" << endl;}
virtual ~Person(){cout << "Person destructor" << endl;}
//...
private:
string name;
string address;
};
class Student: public Person{
public:
Student(){cout << "Student constructor" << endl;}
Student(const Student &s):Person(s){cout << "Student copy constructor" << endl;}
~Student(){cout << "Student destructor" << endl;}
//...
private:
string schoolName;
string schoolAddress;
};
bool validateStudent(Student s){
//...
return true;
}
int main(){
Student plato;
bool platoIsOK = validateStudent(plato);
}
输出:
Personconstructor
Student constructor
Person copy constructor
Student copy constructor
Student destructor
Person destructor
Student destructor
Person destructor
解析:这里调用了四次构造函数和四次析构函数,其中pass-by-value方式调用了两次构造函数和两次析构函数,加上Student的两次string类型的成员变量和Person的两次string类型的成员变量,pass-by-value一共调用了六次构造函数和六次析构函数
示例:pass-by-reference-to-const
#include <iostream>
#include <string>
using namespace std;
class Person{
public:
Person(){cout << "Person constructor" << endl;}
Person(const Person &){cout << "Person copy constructor" << endl;}
virtual ~Person(){cout << "Person destructor" << endl;}
//...
private:
string name;
string address;
};
class Student: public Person{
public:
Student(){cout << "Student constructor" << endl;}
Student(const Student &s):Person(s){cout << "Student copy constructor" << endl;}
~Student(){cout << "Student destructor" << endl;}
//...
private:
string schoolName;#include <iostream>
#include <string>
using namespace std;
class Person{
public:
Person(){cout << "Person constructor" << endl;}
Person(const Person &){cout << "Person copy constructor" << endl;}
virtual ~Person(){cout << "Person destructor" << endl;}
//...
private:
string name;
string address;
};
class Student: public Person{
public:
Student(){cout << "Student constructor" << endl;}
Student(const Student &s):Person(s){cout << "Student copy constructor" << endl;}//这里从pass-by-value改为pass-by-reference-to-const
~Student(){cout << "Student destructor" << endl;}
//...
private:
string schoolName;
string schoolAddress;
};
bool validateStudent(const Student &s){
//...
return true;
}
int main(){
Student plato;
bool platoIsOK = validateStudent(plato);
}
string schoolAddress;
};
bool validateStudent(Student s){
//...
return true;
}
int main(){
Student plato;
bool platoIsOK = validateStudent(plato);
}
输出:
Personconstructor
Student constructor
Student destructor
Person destructor
解析:这里由于pass-by-reference-to-const产生的函数调用为零,因为没有任何新对象被创建
示例3:pass-by-value导致slicing
#include <iostream>
#include <string>
using namespace std;
class Window{
public:
//...
virtual void display()const {cout << "window" << endl;}
};
class WindowWithScrollBars: public Window{
public:
virtual void display() const {cout << "window with scroll bars" << endl;}
};
void printNameAndDisplay(Window w){
w.display();
}
int main(){
WindowWithScrollBars wwsb;
printNameAndDisplay(wwsb);
}
输出:
window
解析:采用pass-by-value会调用Window类的copy constructor构造参数w将它构造成Window类,所以调用display是总是调用Window::display,而不会是WindowWithScrollBars::display
示例4:通过pass-by-reference-to-const解决slicing问题
#include <iostream>
#include <string>
using namespace std;
class Window{
public:
//...
virtual void display()const {cout << "window" << endl;}
};
class WindowWithScrollBars: public Window{
public:
virtual void display() const {cout << "window with scroll bars" << endl;}
};
void printNameAndDisplay(const Window &w){ //这里使用pass-by-reference-to-const
w.display();
}
int main(){
WindowWithScrollBars wwsb;
printNameAndDisplay(wwsb);
}
输出:window with scroll bars
解析:printNameAndDisplay的参数w指向的是一个WindowWithScrollBars,所以它会调用WindowWithScrollBars::display