由临时对象引发的对常引用的思考

简介: 由临时对象引发的对常引用的思考

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))才能成功调用拷贝构造函数


目录
相关文章
|
11月前
|
编译器 C++ 容器
【c++11】 左值引用和右值引用
【c++11】 左值引用和右值引用
|
10月前
|
C++
C++11 右值引用和移动语义(三)
C++11 右值引用和移动语义
35 0
|
3月前
|
存储 C++
C++程序中的对象指针
C++程序中的对象指针
30 1
|
2月前
|
编译器
右值引用和移动语义
右值引用和移动语义
|
10月前
|
编译器 C++ 容器
C++11 右值引用和移动语义(二)
C++11 右值引用和移动语义
30 0
|
3月前
|
C++
33对象指针
33对象指针
17 0
|
3月前
|
消息中间件 Kubernetes NoSQL
c++11左值引用与右值引用
c++11左值引用与右值引用
|
10月前
|
C++
C++11 右值引用和移动语义(一)
C++11 右值引用和移动语义
25 1
|
存储 编译器 C++
右值引用与移动语义
右值引用与移动语义
80 0
|
编译器
拷贝构造与深浅拷贝
一、拷贝构造函数 二、拷贝初始化 三、深浅拷贝
64 0