【C++】8.类和对象(6)

news2024/9/24 6:11:59

文章目录

  • 5. 内部类
  • 6. 匿名对象
  • 7. 对象拷贝时的编译器优化


5. 内部类

  • 如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。

  • 内部类默认是外部类的友元类。

  • 内部类本质也是一种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使用,那么可以考虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其他地方都用不了。

class A
{
private:
	static int _k;//静态成员变量存储在静态区里面,所以计算大小的时候不会被计算
	int _h = 1;//4字节

public:
	class B // B默认就是A的友元
	{
	public:
		void foo(const A& a)
		{
			cout << _k << endl; //OK
			cout << a._h << endl; //OK
		}
	private:
		int _b;
	};
};

int A::_k = 1;

int main()
{
	cout << sizeof(A) << endl;
	A::B b;
	return 0;
}

打印:

4

打印4说明只需要计算int _h = 1;是4字节,不需要计算B

这说明A对象里面没有B对象。

AB的关系其实就像下面一样,AABB

B定义到A里面是说B受到A这个类域的限制。

class A
{
private:
	static int _k;//静态成员变量存储在静态区里面,所以计算大小的时候不会被计算
	int _h = 1;
public:
};

class B // B默认就是A的友元
{
public:
	void foo(const A& a)
	{
		cout << _k << endl; //OK
		cout << a._h << endl; //OK
	}
private:
	int _b;
};

int A::_k = 1;

int main()
{
	cout << sizeof(A) << endl;
	A::B b;
	return 0;
}

当然,如果把B类放到A类的private里面,那么就无法通过A::B b;来访问了。

class A
{
private:
	static int _k;//静态成员变量存储在静态区里面,所以计算大小的时候不会被计算
	int _h = 1;//4字节

	class B // B默认就是A的友元
	{
	public:
		void foo(const A& a)
		{
			cout << _k << endl; //OK
			cout << a._h << endl; //OK
		}
	private:
		int _b;
	};
};

int A::_k = 1;

int main()
{
	cout << sizeof(A) << endl;
	A::B b;//会报错
	return 0;
}

学完内部类后我们也可以这么写之前的那题:

4f69881563edf4761810f245997b7a8d

代码:

class Solution {
    // 内部类
    class Sum
    {
    public:
        	Sum()
        	{
          	  _ret += _i;
          	  ++_i;
        	}
    };
    static int _i;
    static int _ret;
public:
    int Sum_Solution(int n) {
        // 变长数组
        Sum arr[n];
        return _ret;
    }
};
int Solution::_i = 1;
int Solution::_ret = 0;

6. 匿名对象

  • 用类型(实参) 定义出来的对象叫做匿名对象,相比之前我们定义的 类型 对象名(实参) 定义出来的叫有名对象

  • 匿名对象生命周期只在当前一行,一般临时定义一个对象当前用一下即可,就可以定义匿名对象。

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 aa1;//有名对象(有名字的对象)
    
    //A aa1();// 有名对象不能这么定义对象,因为编译器无法识别下面是一个函数声明,还是对象定义
    
    // 但是我们可以这么定义匿名对象,匿名对象的特点不用取名字,
    // 但是他的生命周期只有这一行,我们可以看到下一行他就会自动调用析构函数
    A();
    A(1);
    A aa2(2);
    
    //原本我们这样调用对象的
    Solution s1;
    cout << s1.Sum_Solution(10) << endl;
    // 匿名对象在这样场景下就很好用,当然还有一些其他使用场景,这个我们以后遇到了再说
    cout << Solution().Sum_Solution(10) << endl;
    return 0;
}
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};

void func(A aa = A(1))//缺省参数一般是给常量和自定义变量,现在可以给个匿名对象了
{}

int main()
{
	func();

	const A& r = A();//匿名对象可以引用,但是匿名对象和临时对象一样有常性。不过const引用会延长他的生命周期。

	return 0;
}


7. 对象拷贝时的编译器优化

  • 现代编译器会为了尽可能提高程序的效率,在不影响正确性的情况下会尽可能减少一些传参和传返回值的过程中可以省略的拷贝。

  • 如何优化C++标准并没有严格规定,各个编译器会根据情况自行处理。当前主流的相对新一点的编译器对于连续一个表达式步骤中的连续拷贝会进行合并优化,有些更新更"激进"的编译器还会进行跨行跨表达式的合并优化。

#include<iostream>
using namespace std;
class A
{
public:
    A(int a = 0)
        :_a1(a)
    {
        cout << "A(int a)" << endl;
    }
    A(const A& aa)
        :_a1(aa._a1)
    {
        cout << "A(const A& aa)" << endl;
    }
    A& operator=(const A& aa)
    {
        cout << "A& operator=(const A& aa)" << endl;
        if (this != &aa)
        {
            _a1 = aa._a1;
        }
        return *this;
    }
    ~A()
    {
        cout << "~A()" << endl;
    }
private:
    int _a1 = 1;
};

void f1(A aa)
{}

A f2()
{
    A aa;
    return aa;
}

int main()
{
    // 优化
	A aa0 = 1;
	cout << endl;
    // 传值传参
    A aa1;
    f1(aa1);
    cout << endl;
    // 隐式类型,连续构造+拷贝构造->优化为直接构造
    f1(1);
    // 一个表达式中,连续构造+拷贝构造->优化为一个构造
    f1(A(2));
    cout << endl;
    cout << "***********************************************" << endl;
    // 传值返回
    // 返回时一个表达式中,连续拷贝构造+拷贝构造->优化一个拷贝构造 (vs2019 debug)
    // 一些编译器会优化得更厉害,进行跨行合并优化,直接变为构造。(vs2022 debug)
    f2();
    cout << endl;
    // 返回时一个表达式中,连续拷贝构造+拷贝构造->优化一个拷贝构造 (vs2019 debug)
    // 一些编译器会优化得更厉害,进行跨行合并优化,直接变为构造。(vs2022 debug)
    A aa2 = f2();
    cout << endl;
    // 一个表达式中,连续拷贝构造+赋值重载->无法优化
    aa1 = f2();
    cout << endl;
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【信号与系统】2、系统

1、线性系统 举例&#xff1a; &#xff08;1&#xff09;&#xff0c;是线性系统 &#xff08;2&#xff09;&#xff0c;是线性系统 &#xff08;3&#xff09;&#xff0c;微分器&#xff0c;是线性系统 &#xff08;4&#xff09;&#xff0c;积分器&#xff0c;是线性…

具身智能火了,但规模落地还需时间

作者 | 辰纹 来源 | 洞见新研社 “人工智能下一个浪潮是具身智能&#xff0c;即能理解、推理并与物理世界互动的智能系统”&#xff0c; 英伟达CEO黄仁勋去年在ITF World 2023半导体大会上的预测正在成为现实。 5月份&#xff0c;日本横滨召开的国际顶级机器人学术会议&…

专业120+总分400+中国科学技术大学843信号与系统考研经验中科大电子信息通信工程,生物医学工程,苏医工,真题,大纲,参考书。

经过将近一年的复习备考&#xff0c;专业843信号与系统120&#xff0c;总分400&#xff0c;顺利上岸朝思暮想的中科大。总结一些自己的备考经验&#xff0c;希望能给大家一些参考&#xff0c;少走弯路。首先讲一下大家最关注的专业课&#xff1a;843信号与系统 中科大843专业课…

动态规划算法:10.路径问题_地下城游戏_C++

目录 题目链接&#xff1a;174. 地下城游戏 - 力扣&#xff08;LeetCode&#xff09; 一、题目解析 题目&#xff1a;​编辑 解析&#xff1a; 二、算法原理 1、状态表示 2、状态转移方程 状态转移方程推理&#xff1a; 3、初始化 dp表初始化: 特殊位置初始化&#…

Vue学习(五)生命周期、组件

生命周期 生命周期&#xff0c;又名生命周期回调函数、生命周期函数、生命周期钩子。 生命周期是Vue在关键时刻帮我们调用的一些特殊名称的函数。 生命周期函数的名字不可更改&#xff0c;但是函数的具体内容是程序员根据需求写的。 生命周期中的this指向的是vm或者组件实例…

NFTScan | 09.16~09.23 NFT 市场热点汇总

欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总。 周期&#xff1a;2024.09.16~ 2024.09.22 NFT Hot News 01/ ​DeGods 推出代币 DEGOD&#xff0c;用户可通过 DeGods、y00ts 或 DUST 进行转换 9 月 16 日&#xff0c;Solana NFT 项目 DeGods 推出代币…

综合题第二题(路由器的配置)

题目 如何计算子网掩码 我们可以观察到上图的IP地址后面有“/26”、“30”。我们都知道子网掩码是由多个连续“1”和多个连续“0”组成的&#xff0c;“、26”表示子网掩码的二进制表达中有26个1。 例如&#xff1a;156.95.9.128/26 1111 1111.1111 1111.1111 1111.1100 0000…

idea插件开发系列1-环境搭建

前言 还记着10多年前有幸接触了eclipse插件开发&#xff0c;10多年后的今天有开发了idea的插件&#xff0c;真是一个轮回&#xff01; 为什么要学习idea插件开发呢&#xff1f; 目前公司使用自己的MVC框架&#xff0c;没有相应的idea插件支持&#xff08;如类似mybatis插件可…

基于51单片机智能家居监控系统设计

文章目录 前言资料获取设计介绍功能介绍设计程序具体实现截图设计获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对…

计算机毕业设计hadoop+hive航班预测系统 飞机票航班数据分析可视化大屏 机票预测 机票爬虫 飞机票推荐系统 大数据毕业设计

《HadoopHive航班预测系统》开题报告 一、课题背景与意义 随着全球航空业的快速发展&#xff0c;航班数据呈现出爆炸性增长的趋势。这些数据包含了航班时间、航线、价格、乘客量、天气条件等多种信息&#xff0c;对于航空公司来说&#xff0c;如何高效处理和分析这些数据&…

大模型培训讲师叶梓:Llama Factory 微调模型实战分享提纲

LLaMA-Factory ——一个高效、易用的大模型训练与微调平台。它支持多种预训练模型&#xff0c;并且提供了丰富的训练算法&#xff0c;包括增量预训练、多模态指令监督微调、奖励模型训练等。 LLaMA-Factory的优势在于其简单易用的界面和强大的功能。用户可以在不编写任何代码的…

高校大数据实训管理平台怎么选择?

泰迪智能科技大数据实训管理平台分为多个方向包括&#xff1a;人工智能方向、大数据方向、商务数据分析方向&#xff0c;不同高校可以结合高校情况选择合适自己院校的相关产品平台。 高校实训管理平台是实验室模块的核心母平台&#xff0c;对实验室的所有课程及实训资源进行统…

【题解】CF2013A

首先抽自己一巴掌&#xff0c;A题自信提交直接WA&#xff0c;故写此题解警示一下&#xff08;顺便水一水&#xff09;。 翻译 原题链接 思路 显然&#xff0c;若搅拌机单位时间能处理的水果数 x x x小于人每次丢进去的数量 y y y&#xff0c;那人只需要一直扔进去就好了&…

【d48】【Java】【力扣】LCR 123. 图书整理 I

思路 方法1&#xff1a;放进list,将list倒置&#xff0c;利用stream&#xff0c;将list改为int类型 方法2&#xff1a;递归&#xff1a;递归通用思路&#xff1b;明确每一层做什么确定返回值确定什么地方接收下层的返回值 每一层&#xff1a;调用下层&#xff0c;然后把自己…

护理陪护小程序|陪护系统||陪护系统开发

在当今社会&#xff0c;随着人口老龄化的加剧和家庭结构的变化&#xff0c;护理与陪护服务的需求日益增长。为了更好地满足这一市场需求&#xff0c;并提升服务效率与质量&#xff0c;护理陪护小程序应运而生。这类小程序不仅为用户提供了便捷、高效的服务预约与管理平台&#…

DANN GRL

域自适应是指在目标域与源域的数据分布不同但任务相同下的迁移学习&#xff0c;从而将模型在源域上的良好性能迁移到目标域上&#xff0c;极大地缓解目标域标签缺失严重导致模型性能受损的问题。 介绍一篇经典工作 DANN &#xff1a; 模型结构 在训练阶段需要预测如下两个任务…

Redis:持久化

1. Redis持久化机制 Redis 支持 RDB 和 AOF 两种持久化机制&#xff0c;持久化功能有效地避免因进程退出造成数据丢失问题&#xff0c; 当下次重启时利⽤之前持久化的文件即可实现数据恢复。 2.RDB RDB 持久化是把当前进程数据⽣成快照保存到硬盘的过程&#xff0c;触发 RDB…

【第十一章:Sentosa_DSML社区版-机器学习之分类】

目录 11.1 逻辑回归分类 11.2 决策树分类 11.3 梯度提升决策树分类 11.4 XGBoost分类 11.5 随机森林分类 11.6 朴素贝叶斯分类 11.7 支持向量机分类 11.8 多层感知机分类 11.9 LightGBM分类 11.10 因子分解机分类 11.11 AdaBoost分类 11.12 KNN分类 【第十一章&…

Rustrover2024.2 正式发布:个人非商用免费,泰裤辣

如果这个世界本身 已经足够荒唐 那究竟什么才能算是疯狂 爱情就是这样 一旦错过了 就会有另一个人代替 我们知道 jetbrains 在今年的早些时候正式为 rust 语言发布了专用的 IDE &#xff0c;也就是 rustrover。如今 rustrover 也正式跻身为 jetbrains IDE 系列的一员猛将。…

Dynamic Connected Networks for Chinese Spelling Check(ACL2021)

Dynamic Connected Networks for Chinese Spelling Check(ACL2021) 一&#xff0e;概述 文中认为基于bert的非自回归语言模型依赖于输出独立性假设。不适当的独立性假设阻碍了基于bert的模型学习目标token之间的依赖关系&#xff0c;从而导致了不连贯的问题。为些&#xff0c…