最近在看C++ primer第七章的类Sales_data类中有那么三个函数,返回类型都是&引用类型的,这是什么意思呢?如果不是引用类型的会怎么样?
对于combine的引用,我个人的猜想是因为要返回解引用的*this指针,所以函数返回类型是引用类型,不知道我的猜想对不对?
至于另外两个,书上说IO库不支持拷贝,所以要用引用,这个有点深奥
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
istream& read(istream& is, Sales_data& item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = item.units_sold * price;
return is;
}
ostream& print(ostream& os, const Sales_data& item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
return os;
}
值类型是类时,在传递参数、函数返回时,会发生一次额外的拷贝构造,而引用则返回类对象的别名。
就拿你的代码举例,Sales_data& Sales_data::combine(const Sales_data& rhs)
函数返回值是引用类型(Sales_data& ),可不可以是值类型?答案是可以的,原来的combine相当于
Sales_data Sales_data::combine(const Sales_data& rhs) // 返回值是值类型,而非引用类型
{
...
Sales_data temp(*this); // 编译器生成一个临时对象:用*this在栈上拷贝构造temp
return temp;
}
// 调用处
Sales_data a, b;
Sales_data d = a.combine(b);
同样的,在传参的时候,如果是值传递,而不是引用传递,就会有一次额外的拷贝构造调用。而且,新构造的对象并非原来的对象,但是引用传递的对象却是原来的对象。
Sales_data& Sales_data::combine(const Sales_data primary_obj) // 参数是值类型,而非引用类型
{
Sales_data temp(primary_obj);
...
return *this;
}
IO库不用值传递(拷贝),而是用引用,我想主要是基于上面2点考虑:
1)效率,值传递会多一次对象拷贝构造,这个开销不小,而且并不是必须的;
2)对拷贝构造的对象的修改,并不会对原对象产生任何影响。
看一下iostream的源码就知道,他的拷贝构造函数是delete的,c++11之前他的拷贝构造函数是protected的,因为输入输出一般来说就一份,内部所引用的具体输入输出硬件:键盘,屏幕,网络,文件等等,一般来说一个对象只针对一份,所以允许复制的话,将有两个所有者对其操作,必然容易引起冲突,因此被设计不可拷贝的