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指针解引用了,但是我们实际问题和问题三一样。

最后,感谢大家的支持!

相关推荐
小oo呆8 分钟前
【学习心得】Python函数参数中的两个特殊分隔符
开发语言·python
x10n913 分钟前
微软 VC++ 运行库合集VCRedistPack
开发语言·c++·microsoft·vc++运行库·dll报错
qz_Serene18 分钟前
C++:string(底层,常用接口,具体题目,模拟实现)
开发语言·c++
NiceBlueChai18 分钟前
Qt 跨线程传递多容器嵌套结构:一次 Release 实测
开发语言·qt
念何架构之路19 分钟前
go-grpc逻辑架构图
开发语言·后端·golang
SEO_juper20 分钟前
AI 爬虫 robots.txt 检查工具:你的站是不是把 AI 挡在门外了
开发语言·人工智能·爬虫·python·外贸独立站
木圭的AI时代指南22 分钟前
实测 MiniMax M3.1 Flash:同一道 Three.js 大题,两个 agent 差出 4.6 倍
开发语言·javascript·ecmascript
星恒讯工业路由器24 分钟前
工业路由器在中小 IoT 场景的选型与适配实践:从标准品到定制化的技术路径
开发语言·网络·物联网·php·工业路由器选型·工业网关odm·链路冗余切换
OKkankan30 分钟前
python 进阶(三):面向对象进阶——从“会写 class”到设计可维护的后端对象
开发语言·数据结构·python
魔都吴所谓39 分钟前
【Python】 多线程 & 多进程&协程 常见题 + 应用场景整理
开发语言·python