C++引用详解
关于临时对象返回和常引用问题
上代码
#include<stdio.h> #include<iostream> using namespace std; class Test { public: Test() { }; Test(int x1, int y1) :x(x1), y(y1) { }; Test(Test& T) { x = T.x; y = T.y; cout << "我是拷贝构造" << endl; } Test operator+(Test c) { return Test(this->x + c.x, this->y + c.y); } void pri() { cout << x << "---" << y << endl; } protected: int x, y; }; int main() { Test o1(1, 2); Test o2(2, 3); Test r; r = o1 + o2; r.pri(); return 0; }
为什么这里会报错呢,没有合适的拷贝构造函数
来看16行
return Test(this->x + c.x, this->y + c.y);
暂且称为Test(xxx),这里使用类名(参数列表)创建了一个无名对象,在这个函数体内,他是无名临时对象,函数体结束,就被销毁了。而return这一句,编译器内部的操作是
1.创建一个新对象,用拷贝构造函数存下这个无名对象
2.然后返回给调用这个函数的地方
即----->Test A(Test(this->x + c.x, this->y + c.y))
然后把A返回出去
r = o1 + o2就变成了r=A
那么在
Test A(Test(this->x + c.x, this->y + c.y))
这一句的拷贝构造函数中,就出现了需要注意的地方
Test(Test& T) { x = T.x; y = T.y; cout << "我是拷贝构造" << endl; }
如果拷贝构造函数像初学者一样写,那么编译就会报错,为什么呢,先来看下面的例子
int a=1; int &b=a; int &c=5;
&b=a这一句是合法的,而…&c=5是非法操作
声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。
a本身有地址,当然能引用,而5呢,复制完即销毁,没有地址,当然不能引用,若是c引用了,用着用着5没了,那c去哪??那么想引用5怎么变呢,
这里就需要使用常引用
const int &c=5;
用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。
把5变成常量,存在常量区,那么一个常量自然可以引用咯
同理:对于临时变量Test(xxx)而言,想要引用它,就要把它变成常量,所以拷贝构造函数要改成常引用的形式
Test(const Test& T) {}
这样Test A(Test(this->x + c.x, this->y + c.y))才能成功调用拷贝构造函数