在C++中,由于以下原因,变量通过引用传递:
1)修改调用者函数的局部变量:引用(或指针)允许被调用函数修改调用者函数的局部变量。例如,考虑以下示例程序,其中fun()能够修改main()的局部变量x 。
CPP
#include
using namespace std;
void fun(int& x) { x = 20; }
int main()
{
int x = 10;
fun(x);
cout << "New value of x is " << x;
return 0;
}
C
class Employee {
private:
string name;
string desig;
// More attributes and operations
};
void printEmpDetails(Employee emp)
{
cout << emp.getName();
cout << emp.getDesig();
// Print more attributes
}
C
void printEmpDetails(const Employee& emp)
{
cout << emp.getName();
cout << emp.getDesig();
// Print more attributes
}
C
#include
#include
using namespace std;
class Pet {
public:
virtual string getDescription() const
{
return "This is Pet class";
}
};
class Dog : public Pet {
public:
virtual string getDescription() const
{
return "This is Dog class";
}
};
void describe(Pet p)
{ // Slices the derived class object
cout << p.getDescription() << endl;
}
int main()
{
Dog d;
describe(d);
return 0;
}
C++
#include
#include
using namespace std;
class Pet {
public:
virtual string getDescription() const
{
return "This is Pet class";
}
};
class Dog : public Pet {
public:
virtual string getDescription() const
{
return "This is Dog class";
}
};
void describe(const Pet& p)
{ // Doesn't slice the derived class object.
cout << p.getDescription() << endl;
}
int main()
{
Dog d;
describe(d);
return 0;
}
C++
#include
using namespace std;
class base {
public:
virtual void show()
{ // Note the virtual keyword here
cout << "In base \n";
}
};
class derived : public base {
public:
void show() { cout << "In derived \n"; }
};
// Since we pass b as reference, we achieve run time
// polymorphism here.
void print(base& b) { b.show(); }
int main(void)
{
base b;
derived d;
print(b);
print(d);
return 0;
}
输出:
x的新值为20
2)对于传递大型参数:如果参数较大,则通过引用(或指针)传递效率更高,因为仅实际传递地址,而不传递整个对象。例如,让我们考虑以下Employee类和一个用于打印Employee详细信息的函数printEmpDetails() 。
C
class Employee {
private:
string name;
string desig;
// More attributes and operations
};
void printEmpDetails(Employee emp)
{
cout << emp.getName();
cout << emp.getDesig();
// Print more attributes
}
上面的代码存在的问题是:每次调用printEmpDetails()时,都会构造一个新的Employee对象,其中涉及创建所有数据成员的副本。因此,更好的实现方法是将Employee作为参考。
C
void printEmpDetails(const Employee& emp)
{
cout << emp.getName();
cout << emp.getDesig();
// Print more attributes
}
这一点仅对结构和类变量有效,因为我们对于int,char等基本类型没有任何效率优势。
3)为避免对象切片: 如果我们将子类的对象传递给需要超类对象的函数,则按值传递的对象将被切片。例如,考虑以下程序,它打印“ This is Pet Class”。
C
#include
#include
using namespace std;
class Pet {
public:
virtual string getDescription() const
{
return "This is Pet class";
}
};
class Dog : public Pet {
public:
virtual string getDescription() const
{
return "This is Dog class";
}
};
void describe(Pet p)
{ // Slices the derived class object
cout << p.getDescription() << endl;
}
int main()
{
Dog d;
describe(d);
return 0;
}
输出:
这是宠物课
如果我们在上述程序中使用按引用传递,则它会正确打印“ This is Dog Class”。请参阅以下修改的程序。
C++
#include
#include
using namespace std;
class Pet {
public:
virtual string getDescription() const
{
return "This is Pet class";
}
};
class Dog : public Pet {
public:
virtual string getDescription() const
{
return "This is Dog class";
}
};
void describe(const Pet& p)
{ // Doesn't slice the derived class object.
cout << p.getDescription() << endl;
}
int main()
{
Dog d;
describe(d);
return 0;
}
输出:
这是狗班
这一点对于基本数据类型(例如int,char等)也无效。
4)在函数实现运行时多态
我们可以通过将对象作为对其的引用(或指针)进行传递来使函数变为多态。例如,在以下程序中,print()接收对基类对象的引用。如果传递了基类对象,则print()调用基类函数show();如果传递了派生类对象,则调用派生类函数show()。
C++
#include
using namespace std;
class base {
public:
virtual void show()
{ // Note the virtual keyword here
cout << "In base \n";
}
};
class derived : public base {
public:
void show() { cout << "In derived \n"; }
};
// Since we pass b as reference, we achieve run time
// polymorphism here.
void print(base& b) { b.show(); }
int main(void)
{
base b;
derived d;
print(b);
print(d);
return 0;
}