C++基础之this指针的详解

***************************************************

更多精彩,欢迎进入:http://shop115376623.taobao.com

***************************************************


关于C++中的this指针,建议大家看看这篇文章,《C++中的this指针》,供参考。

  this指针是一个特殊的指针,当类的某个非静态的成员函数在执行时,就会存在this指针。它指向类的一个对象,且这个对象的某个成员函数正在被调用。

  this指针的名字始终是this,而且总是作为隐含参数传递给每一个被声明的成员函数,例如:

  实际编程时函数的声明不需要包含这个参数。

 

  当程序中调用某个对象的成员函数时,编译器会把该对象的地址加入到参数列表中,感觉上就好象函数采用了上面所示的声明,并且是用如下方式来调用的:

  静态成员函数不存在this指针

 

  当调用某个对象的成员函数时,编译器把对象的地址传递给this指针,然后再调用该函数。因此,成员函数你对任何成员的调用实际上都隐式地使用了this指针。

  1.以this指针作为返回值

  使this指针可以允许成员函数返回调用对象给调用者。前面的程序中重载赋值运算符没有返回值,因此不能用如下的形式对字符串进行赋值:

  为了使重载的类赋值机制也能这样方便,必须让赋值函数返回赋值的结果,在这里就是目标对象。当赋值函数执行时,其返回值也恰好是this指针所指的内容。下面的程序对前面那个程序进行了修改,让重载赋值运算符返回了一个Date对象的引用。

 

  2.在链表中使用this指针

  在应用程序中,如果数据结构里有指向自身类型的成员,那么使用this指针会提供更多的方便。下面的程序中建立了一个类ListEntry的链表。

  程序运行时,会提示输入一串姓名,当输入完毕后,键入\"end\",然后程序会逆序显示刚才输入的所有姓名。

 

  程中ListEntry类含有一个字符串和一个指向前一个表项的指针。构造函数从对中获取内存分配给字符串,并把字符串的内容拷贝到内存,然后置链接指针为NULL。析构函数将释放字符串所占用的内存。

  成员函数PrevEntry()返回指向链表前一个表项的指针。另一个成员函数显示当前的表项内容。

  成员函数AddEntry(),它把this指针拷贝给参数的preventry指针,即把当前表项的地址赋值给下一个表项的链接指针,从而构造了一个链表。它并没有改变调用它的listEntry对象的内容,只是把该对象的地址赋给函数的参数所引用的那个ListEntry对象的preventry指针,尽管该函数不会修改对象的数据,但它并不是常量型。这是因为,它拷贝对象的地址this指针的内容给一个非长常量对象,而编译器回认为这个非常量对象就有可能通过拷贝得到的地址去修改当前对象的数据,因此AddEntry()函数在声明时不需要用const。

  希望通过以上内容的介绍,能够给你带来帮助。

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

this指针只能在一个类的成员函数中调用,它表示当前对象的地址。下面是一个例子: void Date::setMonth( int mn ) { month = mn; // 这三句是等价的 
         this->month = mn; (*this).month = mn; } 1. this只能在成员函数中使用。
全局函数,静态函数都不能使用this。
实际上,成员函数默认第一个参数为T* const register this。
如: 
class A{public: int func(int p){}};
其中,func的原型在编译器看来应该是: int func(A* const register this, int p); 
2. 由此可见,this在成员函数的开始前构造的,在成员的结束后清除。
这个生命周期同任一个函数的参数是一样的,没有任何区别。
当调用一个类的成员函数时,编译器将类的指针作为函数的this参数传递进去。如:
A a;
a.func(10);
此处,编译器将会编译成: A::func(&a, 10);
嗯,看起来和静态函数没差别,对吗?不过,区别还是有的。编译器通常会对this指针做一些优化的,因此,this指针的传递效率比较高--如vc通常是通过ecx寄存器来传递this参数。3. 回答
#1:this指针是什么时候创建的?
this在成员函数的开始执行前构造的,在成员的执行结束后清除。

#2:this指针存放在何处? 堆,栈,全局变量,还是其他?
this指针会因编译器不同,而放置的位置不同。可能是栈,也可能是寄存器,甚至全局变量。

#3:this指针如何传递给类中函数的?绑定?还是在函数参数的首参数就是this指针.那么this指针又是如何找到类实例后函数的?
this是通过函数参数的首参数来传递的。this指针是在调用之前生成的。类实例后的函数,没有这个说法。类在实例化时,只分配类中的变量空间,并没有为函数分配空间。自从类的函数定义完成后,它就在那儿,不会跑的。

#4:this指针如何访问类中变量的/?
如果不是类,而是结构的话,那么,如何通过结构指针来访问结构中的变量呢?如果你明白这一点的话,那就很好理解这个问题了。
在C++中,类和结构是只有一个区别的:类的成员默认是private,而结构是public。
this是类的指针,如果换成结构,那this就是结构的指针了。#5:我们只有获得一个对象后,才能通过对象使用this指针,如果我们知道一个对象this指针的位置可以直接使用吗?
this指针只有在成员函数中才有定义。因此,你获得一个对象后,也不能通过对象使用this指针。所以,我们也无法知道一个对象的this指针的位置(只有在成员函数里才有this指针的位置)。当然,在成员函数里,你是可以知道this指针的位置的(可以&this获得),也可以直接使用的。

#6:每个类编译后,是否创建一个类中函数表保存函数指针,以便用来调用函数?
普通的类函数(不论是成员函数,还是静态函数),都不会创建一个函数表来保存函数指针的。只有虚函数才会被放到函数表中。
但是,既使是虚函数,如果编译器能明确知道调用的是哪个函数,编译器就不会通过函数表中的指针来间接调用,而是会直接调用该函数。# 7:这些编译器如何做到的?8:能否模拟实现?
知道原理后,这两个问题就很容易理解了。
其实,模拟实现this的调用,在很多场合下,很多人都做过。
例如,系统回调函数。系统回调函数有很多,如定时,线程啊什么的。举一个线程的例子:
     class A
{
    int n;
        public:
        static void run(void* pThis)
   {A* this_ = (A*)pThis;this_->process();}
       void process(){}};main()
{A a;_beginthread( A::run, 0, &a );}这里就是定义一个静态函数来模拟成员函数。也有许多C语言写的程序,模拟了类的实现。如freetype库等等。
其实,有用过C语言的人,大多都模拟过。只是当时没有明确的概念罢了。
如:
typedef struct student{
int age;
int no;
int scores;
}Student;
void initStudent(Student* pstudent);
void addScore(Student* pstudent, int score);
...
如果你把 pstudent改成this,那就一样了。它相当于:
class Student{
public:
int age; int no; int scores;
void initStudent();
void addScore(int score);
}const常量可以有物理存放的空间,因此是可以取地址的///this指针是在创建对象前创建.
this指针放在栈上,在编译时刻已经确定.
并且当一个对象创建后,并且运行整个程序运行期间只有一个this指针

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

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

相关文章

xcode 开发ios兼容性问题的上下黑边 和 coco2d-x 游戏分辨率适配 ResolutionPolicy::FIXED_WIDTH 都会引起上下黑边问题!!!...

1:Xcode6在iPhone5iOS7模拟器上编译,上下有黑边问题 问题描述: Xcode6环境下,对iPhone5或iPhone5s模拟器,在iOS7或iOS7.1下运行,屏幕上下有黑边。在iOS8下没问题。 问题分析: 这种熟悉的场景又出…

如何用参数化SQL语句污染你的计划缓存

你的SQL语句的参数化总是个好想法。使用参数化SQL语句你不会污染你的计划缓存——错!!!在这篇文章里我想向你展示下用参数化SQL语句就可以污染你的计划缓存,这是非常简单的! ADO.NET-AddWithValue ADO.NET是实现像SQL …

oracle values函数,Oracle文本函数简介

Oracle文本函数使我们常用的函数,下面就为您介绍几种Oracle文本函数的用法,供您参考学习,希望可以让您对Oracle文本函数有更深的认识。(1)UPPER、LOWER和INITCAP这三个函数更改提供给它们的文体的大小写。select upper(product_name) from pr…

c++ int *p = new int()

*************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com *************************************************** int *anew int(120); 申请一个整型变量空间,赋初值为120,并…

Ios: 如何保護iOS束文件屬性列表,圖像,SQLite,媒體文件

Ios: 如何保護iOS束文件屬性列表,圖像,SQLite,媒體文件我創建了Hello World示例項目,然後添加data.plist文件到資源文件夾。現在人們可以很容易得到束文件解壓縮。國際音標。有任何的方法來保護data.plist文件保存在iPhone應用程序…

w3wp oracle,w3wp.exe占用CPU超过50%的处理

w3wp.exe占用CPU超过50%的处理1.查看CPU占用高的进程:任务管理器C:\Documents andSettings\Administrator>iisappW3WP.exe PID: 18008 AppPoolId: STATW3WP.exe PID: 8328 AppPoolId: STATW3WP.exe PID: 17868 AppPoolId: JYCV16W3WP.exe PID: 16652 AppPoolId: …

论两种学习模式

引言 A:你是如何学习的,通过视频、书籍和实践结合?B:不是,一般情况是以一个问题为点去画线和面。 两种学习模式 按部就班方式获取知识(通过书、视频)缺点 信息接收者缺乏深度思考和探索信息发布者的知识体系不一定适合…

启动mq命令 linux,RocketMQ:Linux下启动server和broker的命令

目录QUESTION:RocketMQ:Linux下启动server和broker的命令?ANSWER:一、启动mqnamesrv1.1当前执行1.2后台运行二、启动mqbroker2.1当前执行2.2后台运行QUESTION:RocketMQ:Linux下启动server和broker的命令?ANSWER:一、启动mqnamesrv1.1当前执行进入rocke…

C++中int *p[4]和 int (*q)[4]的区别

*************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com *************************************************** C中int *p[4]和 int (*q)[4]的区别 前者是指针数组,后者是指向数组的指针…

Spring笔记③--spring的命名空间

p:命名空间: xmlns:p"http://www.springframework.org/schema/p" 作用:简化在xml配置bean的属性 在<bean>中使用p:属性名来配置 AOP:命名空间: xmlns:aop"http://www.springframework.org/schema/aop" xsi:schemaLocation: http://www.springframewo…

linux不用命令开启ssh,不用密码也能ssh登陆Linux?

Linux的一个后门引发对PAM的探究1.1 起因今天在搜索关于Linux下的后门姿势时&#xff0c;发现一条命令如下&#xff1a;ln -sf /usr/sbin/sshd /tmp/su; /tmp/su -oPort5555;经典后门。直接对sshd建立软连接&#xff0c;之后用任意密码登录即可。ssh rootx.x.x.x -p 5555这个是…

ScrollView常用(暂时用上了的)代理方法

2019独角兽企业重金招聘Python工程师标准>>> ScrollView常用代理方法: #pragma mark - 滚动结束调用 -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {// 计算 滑动到了第几页double page scrollView.contentOffset.x / scrollView.width;self.p…

笔试题目汇总

C常考笔试题:不用if,while,do-while,for,打印出所有大于0小于k的整数.函数原型void printLess(int k); 解法一:递归方式(刚想出来) [cpp] view plaincopy #include <iostream> using namespace std; void printLess(int k) { switch(--k) { case 0:…

Android ListView性能优化实例讲解

前言&#xff1a; 对于ListView&#xff0c;大家绝对都不会陌生&#xff0c;只要是做过Android开发的人&#xff0c;哪有不用ListView的呢&#xff1f; 只要是用过ListView的人&#xff0c;哪有不关心对它性能优化的呢&#xff1f; 关于如何对ListView进行性能优化&#xff0c;…

Bzoj 3289: Mato的文件管理 莫队,树状数组,逆序对,离散化,分块

3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1539 Solved: 665[Submit][Status][Discuss]Description Mato同学从各路神犇以各种方式&#xff08;你们懂的&#xff09;收集了许多资料&#xff0c;这些资料一共有n份&#xff0c;每份有一个大小和一…

linux头文件 库,Linux操作系统的头文件和库文件搜索路径

一、 头文件1 “”中的头文件&#xff0c;在源文件当前目录查找2 -I 中指定目录 -I可以在CFLAG中指定3 gcc的环境变量 C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH4 编译器预设路径、内定目录&#xff1a;/usr/include/usr/local/include/usr/lib/gcc-lib/i386-lin…

vs2010创建和使用动态链接库(dll)

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 本文将创建一个简单的动态链接库&#xff0c;并编写一个应用台控制程序使用该动态链接…

通用二进制

通用二进制 通用二进制&#xff08;Universal binary&#xff09;是苹果电脑公司提出的一种程序代码&#xff0c;使程序能以本地程序的形式运行在使用PowerPC或者英特尔微处理器&#xff08;x86&#xff09;的麦金塔电脑上&#xff0c;在同一个程序包中同时为两种架构提供最理想…

Python~win32com~Excel

import win32com.client#wwin32com.client.Dispatch("Word.Application") #w.Visible1owin32com.client.Dispatch("Excel.Application") o.Visible1 o.Workbooks.Add() o.Cells(1,1).Value"Hello"转载于:https://www.cnblogs.com/lynclynn/p/530…

linux显示光盘命令行,使用wodim在命令行下烧录光盘

使用wodim在命令行下烧录光盘发布时间:2009-02-27 16:23:11来源:红联作者:zhania作者&#xff1a;linuxtoy出自http://linuxtoy.org/archives/burning-cd-with-wodim.html我们以前介绍的 Linux 光盘烧录工具多为图形化的程序&#xff0c;今天来看看如何使用 wodim 在命令行下烧…