二、类与对象(四)

22 内部类

22.1 内部类的概念

如果一个类定义在另一个类的内部,这个类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员,外部类对内部类没有任何优越的访问权限,也就是说它和定义在一个全局的类没有什么区别,只是受外部类的类域限制。

例:

#include <iostream>
using namespace std;
class A
{
private:int h;
public:class B{private:int b;};
};
int main()
{//B bb; //错误代码A::B bb;//B受A的类域限制return 0;
}

22.2 内部类的特性

  1. 内部类天生就是外部类的友元,即内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。

例:

#include <iostream>
using namespace std;
class A
{
private:static int k;int h;
public:class B // B天生就是A的友元{public:void foo(const A& a){//B可以访问A的私有成员cout << k << endl;//OKcout << a.h << endl;//OK}};
};
int A::k = 1;
int main()
{A::B b;b.foo(A());return 0;
}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 内部类可以定义在外部类的publicprotected、和private也就是任何位置。

  2. sizeof(外部类)= 外部类,和内部类没有任何关系。

例:

#include <iostream>
using namespace std;
class A
{
private:int h;
public:class B{private:int b;};
};
int main()
{A aa;cout << sizeof(aa) << endl;return 0;
}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

23 匿名对象

23.1 匿名对象的引入及特性

以往我们调用成员函数的时候,通常的做法是会先定义一个对象,然后再通过这个对象去调用函数,但是有些时候比如我们在做题目,某个函数只需要被调用一次就可以了,如果定义一个对象才能调用就有些麻烦了,这个时候我们就可以通过匿名对象来对函数进行调用。

以往我们说不能用A aa1();这样的方式来定义对象,因为编译器无法识别这是一个函数声明,还是对象定义。

定义匿名对象的方式和上面的方式类似,但是它不用取名字,而且匿名对象的生命周期只在它出现的那一行

例:

#include <iostream>
using namespace std;
class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};
class Solution {
public:int Sum_Solution(int n) {//...return n;}
};
int main()
{A();cout << "-----" << endl;cout << Solution().Sum_Solution(10) << endl;return 0;
}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从输出结果可以看到,27行的时候定义了一个匿名对象,到了28行后它就自动调用了析构函数。

除此之外,29行还展示了匿名对象的应用场景,即对于那些需要通过对象来调用函数但对象本身并不重要的情况,就可以通过匿名对象进行调用。当然还有一些其他使用场景,这个等以后遇到再说。

23 编译器对拷贝对象时的一些优化

在传参和传返回值的过程中,为减少对象的拷贝,通常编译器会对以下场景做一些优化:

23.1 连续构造和拷贝构造时的优化

#include <iostream>
using namespace std;
class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& aa)" << endl;}A& operator=(const A& aa){cout << "A& operator=(const A& aa)" << endl;if (this != &aa){_a = aa._a;}return *this;}~A(){cout << "~A()" << endl;}
private:int _a;
};int main()
{A aa1 = 1;//构造+拷贝构造return 0;
}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从输出结果可以看到,35行代码本来应该涉及一个构造和一个拷贝构造,但被编译器优化后只涉及一个构造。

23.2 参数类型为引用时的优化

#include <iostream>
using namespace std;
class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& aa)" << endl;}A& operator=(const A& aa){cout << "A& operator=(const A& aa)" << endl;if (this != &aa){_a = aa._a;}return *this;}~A(){cout << "~A()" << endl;}
private:int _a;
};
void Fun2(const A& aa)
{}
int main()
{A aa1 = 1;cout << "-----" << endl;Fun2(aa1);//aa只是aa1的别名,无优化cout << "-----" << endl;Fun2(2);//构造一个临时变量后给别名,无优化cout << "-----" << endl;Fun2(A(3));//return 0;
}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从输出结果可以看到, 当函数参数类型为引用时,因为形参只是实参的一个别名,所以不需要做任何优化。

结论:尽量使用const &传参。

23.3 传值返回时的优化

#include <iostream>
using namespace std;
class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& aa)" << endl;}A& operator=(const A& aa){cout << "A& operator=(const A& aa)" << endl;if (this != &aa){_a = aa._a;}return *this;}~A(){cout << "~A()" << endl;}
private:int _a;
};
void Fun1(A aa)
{}
void Fun2(const A& aa)
{}
A Fun3()
{A aa;//构造return aa;//拷贝构造
}
A Fun4()
{return A();
}
int main()
{A aa1 = 1;cout << "-----" << endl;Fun3();//无优化cout << "-----" << endl;A aa2 = Fun3();//本来应该是一个构造,两个拷贝构造,但被编译器优化为一个构造和一个拷贝构造cout << "-----" << endl;Fun4();//构造+拷贝构造->优化为直接构造A aa3 = Fun4();//构造+拷贝构造+拷贝构造->优化为直接构造cout << "-----" << endl;return 0;
}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从输出结果可以看到,51行代码本来应该涉及一个构造和两个拷贝构造,但被编译器优化为和49行代码一样,只涉及一个构造和一个拷贝构造。除此之外,58行代码直接返回一个匿名对象时,本来应该涉及一个构造和两个拷贝构造,但被编译器优化后,只涉及一个构造。

需要注意的是,下面这种情况无法优化:

A aa1;
aa1 = Fun4();

原因在于,和A aa3 = Fun4();相比,aa1 = Fun4();还涉及到赋值运算符的重载,这将干扰优化的进行。

结论:

  1. 接收返回值对象,尽量以拷贝构造的方式接收,不要赋值接收。
  2. 函数中返回对象时,尽量返回匿名对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/326346.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CNN——LeNet

1.LeNet概述 LeNet是Yann LeCun于1988年提出的用于手写体数字识别的网络结构&#xff0c;它是最早发布的卷积神经网络之一&#xff0c;可以说LeNet是深度CNN网络的基石。 当时&#xff0c;LeNet取得了与支持向量机&#xff08;support vector machines&#xff09;性能相…

如何安装 Python

1.打开浏览器 输入网址 :www.python.org ​ 2.根据电脑系统配置进行下载 ​ 3.确定电脑系统属性&#xff0c;此处我们以win10的64位操作系统为例 ​ 4.安装python 3.6.3 双击下载的安装包 python-3.6.3.exe 注意要勾选&#xff1a;Add Python 3.6 to PATH 点击 Customize…

jdbc源码研究

JDBC介绍 JDBC&#xff08;Java Data Base Connectivity,java数据库连接&#xff09;是一种用于执行SQL语句的Java API&#xff0c;可以为多种关系数据库提供统一访问&#xff0c;它由一组用Java语言编写的类和接口组成。 开发者不必为每家数据通信协议的不同而疲于奔命&#…

从0开始python学习-42.requsts统一请求封装

统一请求封装的目的&#xff1a; 1.去除重复的冗余的代码 2. 跨py文件实现通过一个sess来自动关联有cookie关联的接口。 3. 设置统一的公共参数&#xff0c;统一的文件处理&#xff0c;统一的异常处理&#xff0c;统一的日志监控&#xff0c;统一的用例校验等 封装前原本代…

乐理燥废笔记

乐理燥废笔记 文章目录 终止式小调音阶转调不协和和弦进行大小转调1251 1451转调我的霹雳猫阿诺三全音代理五声音阶又怎样和弦附录&#xff1a;压缩字符串、大小端格式转换压缩字符串浮点数压缩Packed-ASCII字符串 大小端转换什么是大端和小端数据传输中的大小端总结大小端转换…

静态网页设计——旅游网(HTML+CSS+JavaScript)

前言 声明&#xff1a;该文章只是做技术分享&#xff0c;若侵权请联系我删除。&#xff01;&#xff01; 感谢大佬的视频&#xff1a; https://www.bilibili.com/video/BV1KN4y1v7jx/?vd_source5f425e0074a7f92921f53ab87712357b 使用技术&#xff1a;HTMLCSSJS&#xff08;…

在电商狂欢中,什么平台更加对商家有利?

我是电商珠珠 近年来&#xff0c;不管是直播电商也好&#xff0c;电商平台也好&#xff0c;都一直朝着向上走的趋势。 我做电商也已经有5年时间了&#xff0c;期间做过天猫&#xff0c;快手、抖店&#xff0c;团队从原来的几个人&#xff0c;扩大到了70。 在22年10月&#x…

RKE安装k8s及部署高可用rancher之证书私有证书但是内置的ssl不放到外置的LB中 4层负载均衡

先决条件# Kubernetes 集群 参考RKE安装k8s及部署高可用rancher之证书在外面的LB&#xff08;nginx中&#xff09;-CSDN博客CLI 工具Ingress Controller&#xff08;仅适用于托管 Kubernetes&#xff09; 创建集群k8s [rootnginx locale]# cat rancher-cluster.yml nodes:- …

JMS消息发送

目录 概述1.搭建 JMS 环境2.使用JmsTemplate 发送消息3.接收JMS 消息 概述 JMS是一个Java标准&#xff0c;定义了使用消息代理(message broker)的通用API,在2001年提出。长期以来&#xff0c;JMS一直是Java 中实现异步消息的首选方案。在JMS 出现之前每个消息代理都有其私有的…

微服务注册中的负载均衡

背景 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 单体架构&#xff1a;简单方便&#xff0c;高度耦合&#xff0c;扩展性差&#xff0c;适合小型项目。…

一文讲透Python数据分析可视化之直方图(柱状图)

直方图&#xff08;Histogram&#xff09;又称柱状图&#xff0c;是一种统计报告图&#xff0c;由一系列高度不等的纵向条纹或线段表示数据分布的情况。一般用横轴表示数据类型&#xff0c;纵轴表示分布情况。通过绘制直方图可以较为直观地传递有关数据的变化信息&#xff0c;使…

Zoho SalesIQ:构建客户服务知识库的实用工具与指南

客服人员每天都有很多事情要做&#xff0c;包括在线聊天、音频通话、屏幕共享和发送电子邮件。为什么要将搜索常用信息添加到他们列表中呢&#xff1f;因为客户在遇到问题的同时想快速解决问题。所以&#xff0c;我们要使用Zoho SalesIQ客服系统构建客户服务知识库。 一、什么…