我们先来看一个简单的程序:
#include <iostream>
using namespace std;
class A
{
private:
string name;
string addr;
};
void fun(A a)
{
}
int main()
{
A a;
fun(a);
return 0;
}
我们在调用fun函数的时候, 会有形参的拷贝, 会调用A的构造函数, 由于name和addr都是string对象, 所以也会有构造。 也就是有三次构造, 对应的有三次析构, 消耗巨大, 何不以引用来传递呢?
#include <iostream>
using namespace std;
class A
{
private:
string name;
string addr;
};
void fun(A &a) // 引用, 不涉及临时对象的拷贝
{
}
int main()
{
A a;
fun(a);
return 0;
}
这样, 就省略了3次构造, 3次析构, 效率杠杠的。 但是, 上述程序还有个问题, 我们可能担心fun函数改变了a, 所以, 应该加上const, 形成const形式的引用, 如下:
#include <iostream>
using namespace std;
class A
{
private:
string name;
string addr;
};
void fun(const A &a) // const形式的引用, 从此再也不用担心fun函数改变a了
{
}
int main()
{
A a;
fun(a);
return 0;
}
而且, 熟悉C++多态的朋友肯定知道, 拷贝会导致对象切割, 如下:
#include <iostream>
using namespace std;
class A
{
public:
virtual void test()
{
cout << "A" << endl;
}
};
class B : public A
{
public:
virtual void test()
{
cout << "B" << endl;
}
};
void fun(A a) // 对象切割
{
a.test();
}
int main()
{
B b;
fun(b);
return 0;
}
结果为:A
为了避免对象切割, 我们用引用, 为了避免改变b, 我们加const, 于是乎:
#include <iostream>
using namespace std;
class A
{
public:
virtual void test()
{
cout << "A" << endl;
}
};
class B : public A
{
public:
virtual void test()
{
cout << "B" << endl;
}
};
void fun(const A &a)
{
a.test(); // error
}
int main()
{
B b;
fun(b);
return 0;
}
但是, 但是, 但是, 编译不通过, 为什么呢? 因为fun中, a是const引用, 所以不能调用非const函数, 修改为:
#include <iostream>
using namespace std;
class A
{
public:
virtual void test() const // const函数
{
cout << "A" << endl;
}
};
class B : public A
{
public:
virtual void test() const // const函数
{
cout << "B" << endl;
}
};
void fun(const A &a)
{
a.test();
}
int main()
{
B b;
fun(b);
return 0;
}
这样就OK啦, 结果为:B .可见, 对象没有被切割。
最后, 让我们来和Scott Meyers一起来嚷嚷:宁以pass by reference to const替换pass by value.