C++运算符重载引用传参与返回引用的小小心得
1 #include <bits/stdc++.h>
2
3 using namespace std;
4
5 //平面向量类,提供完成向量运算和比较的API
6 //除递增运算符和左移运算符重载外其他函数省略
7
8 class Vec2D
9 {
10 //形参cout和函数返回值使用引用是为了保证拷贝构造函数的调用,以确保全局cout对象唯一
11 //形参vec使用引用是为了提高函数调用效率,也可以不用
12 friend ostream& operator<<(ostream& cout, Vec2D& v); //重载<<运算符
13
14 public:
15 Vec2D(double x, double y); //有参构造函数
16 Vec2D& operator++(); //重载前置++运算符
17 Vec2D operator++(int); //重载后置++运算符
18
19 private:
20 double _x;
21 double _y;
22
23 };
24
25 ostream& operator<<(ostream& cout, Vec2D& v)
26 {
27 cout << '(' << v._x << ',' << v._y << ')' << endl;
28 return cout;
29 }
30
31 Vec2D::Vec2D(double x, double y)
32 {
33 _x = x;
34 _y = y;
35 }
36
37 Vec2D& Vec2D::operator++()
38 {
39 this->_x++;
40 this->_y++;
41 return *this;
42 }
43
44 Vec2D Vec2D::operator++(int)
45 {
46 Vec2D pre = *this;
47 this->_x++;
48 this->_y++;
49 return pre;
50 }
51
52 void test01()
53 {
54 Vec2D v1{ 1, 1 };
55 cout << ++v1 << endl;
56 //cout << v1++ << endl;
57 }
58
59 int main()
60 {
61 test01();
62 return 0;
63 }
我在初学时遇到的一个问题是:重载后置++运算符时,应不应当返回对象的引用?
首先须明确,若令pre = *this,返回引用一定是错误的,因为这是一个开辟在栈内的局部对象,生命周期在成员函数内部,函数结束内存就被释放了;而引用本质是利用指针常量操作对象,利用指针操作不存在的内存是危险的。
其次,若想返回引用,须使用pre = new Vec2D(this->_x, this->_y),这是开辟在堆内的,因此可以安全返回其地址。但与之而来的问题是后续无法对其delete,容易造成内存泄漏。
因此,直接返回对象本身最为妥当,尽管会因此隐式调用一次拷贝构造函数。
与之而来的是第二个问题:代码中注释掉的一行cout << v1++ << endl,会报错:“没有与这些操作数匹配的‘<<’运算符”。
这是因为在定义<<重载时为了提高函数调用运行效率传递对象时,采取了传址调用(引用),而既然需要解引用,就要求实参必须是可以解引用的值,即左值;
而后置++运算符重载返回了一个局部对象,这是一个右值,不能作为左值,所以会报错;
修改方法有二:
(1)把<<运算符重载的形参v修改为传值调用,这样既可以传入一个右值了;
(2)在形参前加上const修饰,即:
friend ostream& operator<<(ostream& cout, const Vec2D& v);
这是因为当const 修饰一个左值引用(型如const Type &)时,表示该左值引用既可以引用一个左值,也可以引用一个右值(字面值或临时对象),而不带 const修饰的左值引用(型如Type &)只能引用一个左值,不能引用一个右值。
C++运算符重载引用传参与返回引用的小小心得的更多相关文章
- 引用传参与reference_wrapper
本文是<functional>系列的第3篇. 引用传参 我有一个函数: void modify(int& i) { ++i; } 因为参数类型是int&,所以函数能够修改传 ...
- ES6中generator传参与返回值
先看两个例子, 1, function* f() { for(var i=0; true; i++) { var reset = yield i; if(reset) { i = -1; } } } ...
- main函数的传参与返回
1.谁给main函数传参(1)调用main函数所在的程序的它的父进程给main函数传参,并且接收main的返回值.2.为什么需要给main函数传参(1)首先,main函数不传参是可以的,也就是说父进程 ...
- C++ 重载运算符返回值 和 返回引用的原因
原因是: +,-,*等返回不了引用,比如+运算符,可以如下重载(为了简单,假设A 只有int x:int y) A operator+(A a,A b) {A sum; sum.x=a.x+b.x ...
- 《挑战30天C++入门极限》C++运算符重载函数基础及其值返回状态
C++运算符重载函数基础及其值返回状态 运算符重载是C++的重要组成部分,它可以让程序更加的简单易懂,简单的运算符使用可以使复杂函数的理解更直观. 对于普通对象来说我们很自然的会频繁使用算数运 ...
- C++二级指针和指针引用传参
前提 一级指针和引用 已经清晰一级指针和引用. 可参考:指针和引用与及指针常量和常量指针 或查阅其他资料. 一级指针和二级指针 个人觉得文字描述比较难读懂,直接看代码运行结果分析好些,如果想看文字分析 ...
- C++基本之 运算符重载
=====>友元运算符#include <iostream> using namespace std; class Test { public: Test(int a = 0) { ...
- C++初阶(运算符重载汇总+实例)
运算重载符 概念: 运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似. 函数原型: 返回值 operator操作符(参数列表) 注意: ...
- C++程序设计方法3:数组下标运算符重载
数组下标运算符重载 函数声明形式 返回类型operator[](参数): 如果返回类型是引用,则数组运算符调用可以出现在等式的左边,接受赋值,即: Obj[index] = value; 如果返回类型 ...
- 《挑战30天C++入门极限》对C++递增(增量)运算符重载的思考
对C++递增(增量)运算符重载的思考 在前面的章节中我们已经接触过递增运算符的重载,那时候我们并没有区分前递增与后递增的差别,在通常情况下我们是分别不出++a与a++的差别的,但的确他们直接是 ...
随机推荐
- java使用MVC编程模型实现1+到100图形界面
MVC概念 MVC编程模型是可以说从提出到现在经久不败,是一种先进的设计结构.能很好的体现个人分工,从而实现前后端分离. M(Model):模型:存储数据的对象.后端操作数据库的. V(View):视 ...
- DSL语言思想的应用
背景 DSL语言的认知 DSL思想的应用 DSL的拓展思考 目标 业务限定 简化逻辑 提高效率 实现 业务提取 业务共性抽离 语法生成 语法实施
- 修改ubuntu 源
查看源的类型,lsb_release -a Codename: jammy ?这里有可能是其他值. 找到同类型的源,修改:/etc/apt/sources.list
- Oracle数据库字符集与国家字符集
一般情况下数据库字符集UTF-8:国家字符集:UTF-16. 服务器端:(oracle服务器端字符集)数据库字符集在创建数据库时指定,在创建后通常不能更改.在创建数据库时,可以指定字符集(CHAR ...
- 简单友好的 Python 任务调度库
schedule :https://github.com/dbader/schedule 该项目人性化的 API 设计,让开发者仅用几行代码就能轻松实现定时任务.它不依赖任何第三方库,全部代码也就一个 ...
- spring mvc基本介绍
1 MVC 盖帘: MVC 是模型(model)-视图(view)-控制器(controller)的缩写, 是一种用于设计编写 Web 应用程序表现层的模式. MVC 设计模式的三大角色: Model ...
- CF908G 题解
题意 传送门 给 \(x\le10^{700}\),问 \(1\) 到 \(x\) 中每个数在各数位排序后得到的数的和.答案模 \(10^9+7\). 题解 学到一种新鲜的转化方式,来记一下. 将 \ ...
- 访问网络共享(net use):发生系统错误 67。找不到网络名。
使用\\ip访问对方共享目录或使用net use \\ip 时: 发生系统错误 67.找不到网络名. 以下几项启用: 1,网卡勾选"Microsoft网络客户端". 2,启用服务& ...
- 有关插槽中scope的问题
暂时不理解
- Navicat连接Oracle时报错ORA-28547:完美解决
1. 先用你的IDEA或者别人的连接到oracle数据库(为了查询版本) 1.1 查询版本SQL:select * from v$version; 2. 引入对应的oci.dll文件 链接:https ...