C++超详细讲解内存空间分配与this指针

 更新时间:2022年05月27日 09:20:30   作者:对象new不出来  
this 指针在C++类和对象中是个很方便实用的关键字,可以简化对象成员属性的调用,使代码表达的含义更加准确;在之前的学习中我们都可以判断变量所占内存空间大小,那么我们创建的类对象所占的内存空间怎么计算呢?想知道this的妙用和类对象占用的内存空间就来跟我学习吧

成员属性和函数的存储

在C++中成员变量和成员函数是分开存储的;

空对象

class Person {};

这里我直接创建一个空的类,并创建一个空的类对象(Person p),利用sizeof关键字输出p所占内存空间,sizeof(p);结果是p=1;

注意:空对象占用内存空间为:

1、C++编译器会给每个空对象分配一个字节空间,是为了区分空对象占内存的位置

2、每个空对象也应该有一个独一无二的内存地址

成员属性的存储

class Person
{
public:
	int m_A;
    static int m_B;
};
int Person::m_B = 100;

首先创建一个简单的Person类,仅仅包含普通成员属性m_A和静态成员变量m_B;然后直接利用sizeof关键字输出p所占内存空间:sizeof(p)

这里的结果是4,而不是8,这是因为静态成员属性不属于类的对象上,无论再加几个静态成员属性,都不会改变结果是4,但是一旦普通成员属性,就会多占用内存空间,比如我加一个float类型的m_c属性,结果是:

成员函数的存储

class Person
{
public:
	void func1(){}
	static void func2(){}//函数都不属于类的对象上,只有非静态成员变量才占用类对象内存空间.
};

这里的Person类中加了普通成员函数和静态成员函数,他们所占内存空间的情况是什么呢,让我们看看结果:

为什么结果和空对象一样呢,因为我开头就说了,C++中成员变量和成员函数是分开存储的,无论是怎样的成员函数都不会占用类对象的内存空间。

小结:函数都不属于类的对象上,只有非静态成员变量才占用类对象内存空间.

this指针的概念

从上面的内容我们知道C++中成员变量和成员函数是分开存储的,每一非静态成员函数只会诞生一份函数实例,也就是说,多个同类型的对象会公用一块代码。

那么问题是:这一块代码是如何区分哪个对象调用自己呢?C++通过特殊的对象指针,this指针解决上述问题。this指针指向被调用的成员函数所属的对象。 this指针是隐含每一个非静态成员函数内的一个指针,不需要定义,直接使用即可。

作用:

1、解决名称冲突

2、返回对象指针*this

解决名称冲突

class Person
{
public:
	Person(int age)
	{
		//this 指针指向 被调用的成员函数 所属的对象
		this->age = age;
	}
	int age;
};

如果我们在编写代码的时候,写的属性太多了,导致成员属性和要传入的变量名相同,就会引发不必要的bug;这时候加上一个this,就可以完美的解决这个问题,this->+属性名,表示指向被调用的成员函数所属的对象,那样我们这个有参构造函数的赋值问题就很好的解决了。

返回对象指针*this

class Person
{
public:
	Person(int age)
	{
		this->age = age;
	}
	Person(const Person& p)
	{
		cout << "拷贝构造函数调用" << endl;
		cout << &p << endl;
	}
	Person& PersonAddAge(Person &p);
	int age;
};
Person& Person::PersonAddAge(Person &p)//返回引用形式地址不变,可以一直加年龄
{
	this->age += p.age;
	cout << &*this << endl;
	return *this;
}

既然this指针指向这个对象的地址,那么*this就代表这个对象的本身,我们做一个年龄相加的成员方法来测试一下;

void test02()
{
	Person p1(10);
	Person p2(10);
	//p1.PersonAddAge(p2).PersonAddAge(p2);//链式调用,返回不加&结果都是20,调用拷贝构造;
	p1.PersonAddAge(p2).PersonAddAge(p2).PersonAddAge(p1).PersonAddAge(p1);
	cout << "p1 年龄为:" << p1.age;
}

大家可以猜猜这样输出的p1的年龄是多少,正确答案是120,其中的“.+函数”属于链式调用,可以快速调用函数,非常之方便好用。之所以是120,原因是这四次调用中,第一次返回p1的年龄属性为10+10,第二次为20+10,第三次为30+30,第四次为60+60=120。是不是看着很简单,但有一个特别注意的事情;相信有心的伙伴已经看到PersonAddAge函数返回值类型是Person &,返回的是类的引用,为什么不返回类的值呢?

这里注意,如果去掉“&”直接返回类的值的话,是没法继续链式调用的,因为前面讲过返回类型为类对象时,这个返回的类对象会被清理掉,然后调用拷贝构造函数在新的地址创建一个类对象,虽然属性结果一样,但是地址变了,可以输出地址看看:

由此可见,去掉“&”四次调用产生了四个地址,而无论多用多少次增加年龄函数,最终结果也只能是20,因为我们输出的是p1的值,从第二次调用,都和p1没关系了,地址已经变了。

再和返回引用的做一下对比:

显而易见,返回类引用不会调用构造函数,p1的地址不变,就能成功的累加年龄了!!!

总结

学习了这一节我们一定要知道C++成员属性和成员函数是分开存储的,以及this指针的妙用;再使用返回对象指针*this的时候,如果想继续对此对象的属性进行修改,一定要加上“&”引用符,如果单纯为了显示的话,可以不加。好了,今天的分享结束了,我们“明天见”。

到此这篇关于C++超详细讲解内存空间分配与this指针的文章就介绍到这了,更多相关C++内存空间分配内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • c++程序字符型的实例讲解

    c++程序字符型的实例讲解

    在本篇文章里小编给大家整理的是一篇关于
    2020-02-02
  • 节序问题:解析大小的端判定

    节序问题:解析大小的端判定

    本篇文章是对大小的端判定进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C++编程中的格式化输出详解

    C++编程中的格式化输出详解

    这篇文章主要介绍了C++编程中的格式化输出详解,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C语言库函数strcpy的使用及模拟实现

    C语言库函数strcpy的使用及模拟实现

    本文主要介绍了C语言库函数strcpy的使用及模拟实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-04-04
  • VC++中图像处理类CBitmap的用法

    VC++中图像处理类CBitmap的用法

    使用VC进行图像处理的时候,CBitmap类为我们提供了丰富的位图处理函数,本文总结了该类的相关函数和常用使用方法,包括加载位图,显示位图,析构CBitmap资源以及在内存中保存位图等内容。
    2015-11-11
  • Qt实现卡牌对对碰游戏(附demo)

    Qt实现卡牌对对碰游戏(附demo)

    本文主要介绍了Qt实现卡牌对对碰游戏,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-10-10
  • error LNK2019: 无法解析的外部符号 问题的解决办法

    error LNK2019: 无法解析的外部符号 问题的解决办法

    error LNK2019: 无法解析的外部符号 问题的解决办法,需要的朋友可以参考一下
    2013-05-05
  • C++中箭头运算符的含义与用法讲解

    C++中箭头运算符的含义与用法讲解

    今天小编就为大家分享一篇关于C++中箭头运算符的含义与用法讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • 详解C++右值引用

    详解C++右值引用

    很多初学者都感觉右值引用晦涩难懂,其实不然。右值引用只不过是一种新的 C++ 语法,真正理解起来有难度的是基于右值引用引申出的2种 C++ 编程技巧,分别为移动语义和完美转发。本节给读者讲解什么是右值引用以及它的基本用法。
    2021-06-06
  • C语言数据结构之二分法查找详解

    C语言数据结构之二分法查找详解

    二分查找算法是在有序数组中用到的较为频繁的一种算法,在未接触二分查找算法时,最通用的一种做法是,对数组进行遍历,跟每个元素进行比较,其时间为O(n),但二分查找算法更优
    2022-02-02

最新评论