C++this指针

我们由一个题目引入:

cpp 复制代码
class Date
{
public:
    void Init(int year=2024, int month=1, int day=27)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    void Print()
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main()
{
    Date d1, d2;
    d1.Init();
    d1.Print();
    d2.Init(2023, 10, 24);
    d2.Print();
    return 0;
}

面对如上代码,我想问Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?

C++中通过引入this指针解决该问题,即:C++编译器给每个"非静态的成员函数"增加了一个隐藏
的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有"成员变量"
的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编
译器自动完成

一.this指针的特性

cpp 复制代码
void Print(Date* const this)
{
    cout << this->_year << "-" <<this-> _month << "-" << this->_day << endl;
}
void Print()
{
    cout << _year << "-" << _month << "-" << _day << endl;
}
//两者等价

此时我们就发现了this指针的特性:

1. this指针的类型:类型* const,即成员函数中,不能给this指针赋值。
2. 只能在"成员函数"的内部使用
3. this指针本质上是"成员函数"的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参。所以对象中不存储this指针。
4. this指针是"成员函数"第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传
递,不需要用户传递

注意点:

1.this指针存在于形参和实参的位置,我们是不可以认为显示的写

2.函数内部可以使用

现在大家简单能理解了this指针,现在我们以问答的方式来深入理解this指针:

1.this 存在哪里 b 因为他是一个形参?(不算放在寄存器的)

a、堆 b、栈 c、静态区 d、常量区 e、对象里面

答案是;b

解析;

首先最不能选的是e,如果this指针放对象里面,它是不是一个指针,那么肯定要占用4/8字节的空间 但是计算的时候我们是不是没有计算this指针的大小,所以排除e

a是动态开辟的空间存放的位置,c静态区是存放全局变量或static修饰的内容,所以这两个也可以排除

对于常量区我们听名字就知道常量区是指在程序运行是不发生改变的量,this指针的对象是没有被const修饰,所以可以改变,而const修饰了this指向,所以this不能改变指向,但是可以改变指向的内容,所以不存在常量区。
综上,this指针在栈区,选b。

问题2:

下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

cpp 复制代码
class A
{
public:
    void print()
    {
        cout << "print()" << endl;
    }
private:
    int _a;
};
int main()
{
    A* ptr = nullptr;
    ptr->print();
    return 0;
}

结果:

所以答案选:C

解析:

我们定义了一个A类指针指向nullptr,然后执行ptr->print(),隐式传递了this指针,但是是空指针,而在我们的成员函数内部并没有涉及到this指针方面内容,所以可以正常调用,这里我们可以检查this指针是不是空:

问题三:

下面程序编译运行结果是?

A、编译报错B、运行崩溃 C、正常运行

cpp 复制代码
class A
{
public:
    void print()
    {
        cout << _a << endl;
    }
private:
    int _a;
};
int main()
{
    A* ptr = nullptr;
    ptr->print();
    return 0;
}

结果发现什么都没输出,可见程序崩了。

答案选:B

补充:(我们没有任何错误,就不可能是在编译时错误,排除A)

解析:

这题和上题区别在于我们我们成员函数与this指针息息相关了,但是该指针是指向空,所以我们我们根本访问不到类的成员变量,所以程序崩了,所以选B

问题四:

下面程序编译运行结果是?

A、编译报错B、运行崩溃 C、正常运行

cpp 复制代码
class A
{
public:
    void print()
    {
        cout << "print()" << endl;
    }
private:
    int _a;
};
int main()
{
    A* ptr = nullptr;
    (*ptr).print();
    return 0;
}

选C

这题我们将前面的放在一起来分析:

我重写一段代码:

cpp 复制代码
class A
{
public:
    void print()
    {
        cout << this << endl;
        cout << _a << endl;
        cout << "print()" << endl;
    }
private:
    int _a=10;
};
int main()
{
    A* ptr = nullptr;
    (*ptr).print();
    return 0;
}

我们发现结果是第三个cout失败导致程序崩了,所以我们的调用:(*ptr).print()理解尤为重要,这里我们可以理解为:虽然我们对ptr指针解引用了,但是我们实际问题和问题三一样。

最后,感谢大家的支持!

相关推荐
7yewh1 分钟前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
waicsdn_haha13 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
_WndProc15 分钟前
C++ 日志输出
开发语言·c++·算法
薄荷故人_16 分钟前
从零开始的C++之旅——红黑树及其实现
数据结构·c++
m0_7482400216 分钟前
Chromium 中chrome.webRequest扩展接口定义c++
网络·c++·chrome
qq_4335545424 分钟前
C++ 面向对象编程:+号运算符重载,左移运算符重载
开发语言·c++
努力学习编程的伍大侠28 分钟前
基础排序算法
数据结构·c++·算法
数据小爬虫@43 分钟前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python
ZJ_.44 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
Narutolxy1 小时前
深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223
开发语言·golang·gin