以前对this指针误解挺多的,在这里单独写一篇进行总结,有不对之处,欢迎指正批评!

一、问题

1.一个类中的不同对象在调用自己的成员函数时,其实它们调用的是同一段函数代码,那么成员函数如何知道要访问哪个对象的数据成员呢?

  没错,就是通过this指针。每个对象都拥有一个this指针,this指针记录对象的内存地址,当我们调用成员函数时,成员函数默认第一个参数为T* const register this,大多数编译器通过ecx寄存器传递this指针,通过 this 这个隐式参数可以访问该对象的数据成员。

2.类的成员函数为什么不能用static和const同时修饰?

  类中用const修饰的函数通常用来防止修改对象的数据成员,函数末尾的const是用来修饰this指针,防止在函数内对数据成员进行修改,而静态函数中是没有this指针的,无法访问到对象的数据成员,与C++ static语义冲突,所以不能。

二、this指针注意点

1.C++中this关键字是一个指向对象自己的一个常量指针,不能给this赋值;

2.只有成员函数才有this指针,友元函数不是类的成员函数,没有this指针;

3.同样静态函数也是没有this指针的,静态函数如同静态变量一样,不属于具体的哪一个对象;

4.this指针作用域在类成员函数内部,在类外也无法获取;

5.this指针并不是对象的一部分,this指针所占的内存大小是不会反应在sizeof操作符上的。

三、this指针的使用

1.在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this,比如类的默认取址运算符重载函数,另外,也可以返回*this的引用,这样可以像输入输出流那样进行“级联”操作;

2.修改类成员变量或参数与成员变量名相同时,如this->a = a (写成a = a编译不过);

3.在class定义时要用到类型变量自身时,因为这时候还不知道变量名,就用this这样的指针来使用变量自身。

四、this指针探讨

1.this指针是什么时候创建的?

  对象new的过程中创建的,具体哪个阶段有待进一步深入了解。

2. this指针存放在何处?

  this指针会因编译器不同而有不同的放置位置。可能是栈,也可能是寄存器,甚至全局变量。在汇编级别里面,一个值只会以3种形式出现:立即数、寄存器值和内存变量值。不是存放在寄存器就是存放在内存中,它们并不是和高级语言变量对应的。

3.为什么C++ NULL对象指针可以调用非虚成员函数,而Java中却不行?

  C++语言是静态绑定的,这也是C++语言和Java语言的一个显著区别。类的成员函数并不与特定对象绑定,所有成员函数共用一份成员函数体,当程序编译后,成员函数的地址即已经确定。另外,C++只关心你的指针类型,不关心指针指向的对象是否有效,C++要求程序员自己保证指针的有效性。况且在有些系统上,地址0也是有效的,理论上完全可以构造一个在地址0上的对象,所以C++中nullptr对象调用成员函数并无不可 。

  nullptr对象调用成员函数时,只要不访问此对象独有的内存部分,则程序正常运行,因为不会使用this,一旦访问此对象的成员变量,则程序崩溃。当然nullptr调用虚方法是不能正常运行的(虚函数有虚表,会占用内存空间),虚方法调用是依赖于this指针的。可以这样理解,你给函数传递了错误的参数,但在该函数内部并没有使用该参数,所以其不影响函数的运行。可以参考下面代码:

  #include <iostream>
using namespace std; class CPeople
{
public:
CPeople(const std::string& name, int age)
: mName(name), mAge(age){}
~CPeople(); void Print()
{
std::cout << "show people info:" << std::endl;
} void PrintInfo()
{
std::cout << "name:" << mName << std::endl;
std::cout << "age:" << mAge << std::endl;
} private: std::string mName;
int mAge; }; int main()
{
CPeople* jon = NULL;
jon->Print(); // 程序正常运行
jon->PrintInfo(); // 程序崩溃,访问非法地址,此时mName和mAge并没有分配空间
return ;
}

五、总结

  引用网上关于this指针的一个经典回答:

  当你进入一个房子后,
  你可以看见桌子、椅子、地板等,
  但是房子你是看不到全貌了。
  对于一个类的实例来说,
  你可以看到它的成员函数、成员变量,
  但是实例本身呢?
  this是一个指针,它时时刻刻指向你这个实例本身。

  对this指针有了一个全面了解后,是否对C++ class理解也更深刻一步?

  写作,能让人更深入的了解事情的本质,慢慢积累,厚积薄发,加油!

作者:KeepHopes
出处:https://www.cnblogs.com/yuwanxian/p/10988736.html
关于作者:专注C++,对大数据、人工智能领域颇感兴趣,请多多赐教!
本文为作者原创,版权归作者和博客园共有,转载或引用请注明出处,谢谢!

C++this详解的更多相关文章

  1. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  2. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  3. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  4. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  5. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  6. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  7. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  8. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  9. Node.js npm 详解

    一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...

  10. .NET应用和AEAI CAS集成详解

    1 概述 数通畅联某综合SOA集成项目的统一身份认证工作,需要第三方系统配合进行单点登录的配置改造,在项目中有需要进行单点登录配置的.NET应用系统,本文专门记录.NET应用和AEAI CAS的集成过 ...

随机推荐

  1. http_load分析(转)

    http://www.cnblogs.com/xuning/p/3954057.html 一.前言 http_load是一款测试web服务器性能的开源工具,从下面的网址可以下载到最新版本的http_l ...

  2. MySql基本数据类型(转)

    说明:通俗的理解:1字节的8位,即1byte=8bit,而这个1byte叫做长度范围,范围的算法是使用bit去求,比如8bit的长度范围是2的8次方,但是在数据库中的类型上是有区分有符号和无符号的,默 ...

  3. hdu1042 (模拟n!)

    题目大意: 求 n.(可能会超过整数范围,这里用数组模拟n!的值) pid=1042">http://acm.hdu.edu.cn/showproblem.php?pid=1042 A ...

  4. long类型字段转换成varchar2类型

    參考文档: How to Convert a Long to Varchar2 (文档 ID 228532.1) /*long类型字段转换成varchar2类型*/ --建表 create table ...

  5. cocos2d-x 2.0下怎样让BOX2D DEBUG DRAW的方法笔记

    原文链接: 这两天玩 cocos2d-x 和 box2d,发现 cocos2d-x 2.0 版本号要使用老方法 debug 渲染会出错.于是找到了新方法来 debug draw: 首先在你的头文件中添 ...

  6. 读取本地json文件,转出为指定格式json 使用Base64进行string的加密和解密

    读取本地json文件,转出为指定格式json   引用添加Json.Net 引用命名空间 using Newtonsoft.Json //读取自定目录下的json文件StreamReader sr = ...

  7. InfoQ中文站特供稿件:Rust编程语言的核心部件

    本文为InfoQ中文站特供稿件.首发地址为: http://www.infoq.com/cn/articles/rust-core-components .如需转载.请与InfoQ中文站联系. 原文发 ...

  8. 10.2.0.1.1 grid control的启动和关闭

    一.Stopping Grid Control and All Its Components 1.停止OMS服务 [oracle@ocm2 oms10g]$ cd /u01/app/oracle/Or ...

  9. ecshop广告宽度值必须在1到1024之间的解决方法

    ecshop加广告出现广告位的宽度值必须在1到1024之间的解决方法,这个问题是今天刚刚发现的,我就郁闷了,如今1024宽度的广告能做什么.你看看京东,天猫,非常多都是大型的横幅广告,这点ecshop ...

  10. 【iOS9系列】-3DTouch开发

    [iOS9系列]-3DTouch开发 第一:简介 3DTouch 是iOS9系统系统下,在iPhone6s(iPhone6s Plus)手机上才能够使用的功能.熟练使用后,发现还是很便捷的. 但是模拟 ...