C++ 中的 this 指针:你不知道的五个小秘密!

开发
this 指针看似简单,但其实在 C++ 中充满了奥秘和强大功能。今天,就让我们一起揭开这个“魔法指针”的神秘面纱。

今天我们来聊聊 C++ 编程中一个你可能常常看到,却不一定完全理解的小东西——那就是this 指针。它看似简单,但其实在 C++ 中充满了奥秘和强大功能。今天,就让我们一起揭开这个“魔法指针”的神秘面纱。

一、this 是谁?

在讲this 指针之前,我们先来理清一个非常基本的概念:C++ 中的对象。你可以把对象想象成一个实体,它是类的实例。当你创建了一个类的对象时,C++ 会为你分配一块内存区域,这块内存区域就是这个对象的“家”。

那么,this 指针其实就是指向当前对象的指针,它告诉你——你当前操作的是哪个对象。它的值就是当前对象的地址。

二、this 怎么用?

1. 访问当前对象的成员

每当你在类的成员函数里使用this 指针时,实际上你是在告诉编译器:“嘿,我现在要操作的这个对象是自己。”

class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}

    void print() {
        std::cout << "当前对象的 value 值是: " << this->value << std::endl;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

在上面的代码里,this->value 等价于value,但加上this 的话,显得你是在“明确”告诉编译器:我现在操作的是当前对象的成员。

2. 用来避免成员名冲突

有时候,我们在类的构造函数或者成员函数里,可能会遇到形参和成员变量同名的情况。此时,this 指针就能帮你“明确”区分是成员变量还是形参。

class MyClass {
public:
    int value;
    MyClass(int value) {
        this->value = value;  // 使用 this 指针区分成员变量和形参
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

在这个例子中,构造函数的参数和类的成员变量同名了。为了避免混淆,我们用this->value 来表示成员变量,确保赋值的是对象的成员。

三、this 有哪些隐藏的秘密?

1. this 只能在成员函数中使用

你不能在类的外部随便用this。它是“专属于”类成员函数的——只有在成员函数内部,编译器才知道你说的this 是哪个对象。

class MyClass {
public:
    int value;

    void setValue(int v) {
        this->value = v;  // 合法,this 是当前对象的指针
    }

    void print() {
        std::cout << "当前对象的值是: " << this->value << std::endl;
    }
};

void test() {
    MyClass obj;
    obj.setValue(10);  // 在成员函数中可以访问 this 指针
    // 在这里就无法使用 this 指针了
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

2. this 指针是一个常量指针

this 不是普通的指针,它是一个常量指针。这意味着你不能改变this 的指向——你不能让它指向其他对象。它永远指向当前对象。

void MyClass::changeThis() {
    this = nullptr;  // 错误!this 是常量指针,不能修改。this指针类型是 const MyClass* this
}
  • 1.
  • 2.
  • 3.

3. this 指针与链式调用

this 指针可以用来实现链式调用,即在同一个语句中连续调用多个成员函数。通过返回*this,可以让一个函数返回当前对象的引用,进而可以继续调用其他成员函数。

class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {}

    MyClass& setValue(int v) {
        value = v;
        return *this;  // 返回当前对象的引用,支持链式调用
    }

    MyClass& print() {
        std::cout << "当前值是: " << value << std::endl;
        return *this;
    }
};

int main() {
    MyClass obj(10);
    obj.setValue(20).print();  // 链式调用
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

四、对象调用成员函数时,this 指针如何传递?(重点)

每当你通过对象调用成员函数时,C++ 编译器会自动把该对象的地址作为this 指针传递给成员函数。这一过程对我们来说是透明的,但是它实际上是如何工作的呢?

来看下面的例子:

#include <iostream>
using namespace std;

class MyClass {
public:
    int value;

    MyClass(int v) : value(v) {}

    void printValue() {
        std::cout << "当前对象的地址是: " << this << std::endl;  // 输出当前对象的地址
        std::cout << "当前对象的 value 值是: " << this->value << std::endl;  // 输出对象的值
    }
};

int main() {
    MyClass obj(10);
    obj.printValue();  // 通过对象调用成员函数

    return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

this 指针如何传递?

当我们调用obj.printValue() 时,C++ 编译器背后实际上会做这样的事情:

(&obj)->printValue();  // 通过 &obj 获取对象地址,将其传递给 printValue 函数
  • 1.

也就是说,&obj 传递给了this 指针,指向了当前调用该函数的对象obj。你可以通过this 指针访问到obj 对象的成员。这个传递过程是隐式的,编译器会自动帮你做。

为了更加直观的理解:

虽然在实际编码中,我们不需要手动传递this 指针,但为了帮助大家更清楚地理解它的作用,我们可以通过显式传递this 指针来做个对比。想象一下,如果我们手动传递this 指针,代码可能会是这样的:

void MyClass::printValue(const MyClass* this) {
    std::cout << "当前对象的地址是: " << this << std::endl;  // 输出当前对象的地址
    std::cout << "当前对象的 value 值是: " << this->value << std::endl;  // 输出对象的值
}
  • 1.
  • 2.
  • 3.
  • 4.

在这种情况下,你可以像这样显式地传递对象的地址:

obj.printValue(&obj);  // 显式传递对象的地址
  • 1.

这里的 &obj 其实就是 obj 对象的地址,它被传递给了printValue() 函数。此时,函数内部的 this 指针指向了 obj,并且你依然可以通过 this 来访问对象的成员。

实际上,这就是我们平时调用成员函数时,编译器自动做的事情:将对象的地址隐式地传递给 this 指针。所以,(&obj)->printValue(); 和obj.printValue(&obj) 在本质上是相同的,只不过前者是自动传递,后者是我们手动传递 this 指针。

五、this 不是万能的!

虽然this 指针在很多情况下非常有用,但它也有局限性:

在静态成员函数中,没有this 指针。因为静态成员函数是属于类的,而不是某个具体的对象,所以它没有“当前对象”的概念。

class MyClass {
public:
    static void staticMethod() {
        // this->value = 10;  // 错误!静态函数没有 this 指针
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

this 指针不适用于全局函数。它只和类的成员函数相关联。

六、总结:this 指针的妙用

  • 指向当前对象:this 指针总是指向当前调用成员函数的对象,让你在代码中明确知道正在操作的是哪个对象。
  • 解决成员变量和参数同名问题:当成员变量和函数参数同名时,this 指针帮你轻松区分它们,避免混淆。
  • 链式调用的秘密武器:通过返回 *this,你可以让多个成员函数在同一行代码中依次执行,让代码更简洁、流畅。
  • 常量指针,保持不变:this 是常量指针,它始终指向当前对象,不能指向其他对象,保证了代码的稳定性和一致性。

理解this 指针,就像是在编写 C++ 代码时拥有了一把“精确定位”的工具。它帮助你更加清晰地理解对象的行为,让你的代码更加清晰、可控。

责任编辑:赵宁宁 来源: 跟着小康学编程
相关推荐

2011-11-29 09:12:22

Web

2020-01-15 12:32:02

大数据人工智能技术

2022-03-10 09:11:33

JavaScrip开发JSON

2010-08-23 09:56:09

Java性能监控

2015-03-09 09:34:04

C语言函数指针

2013-11-25 10:43:32

谷歌微软

2019-07-22 09:46:28

WebSocketNginx服务器

2019-08-30 08:39:33

WebSocketNginx服务器

2011-07-11 15:52:47

RCWindows

2019-09-10 16:25:19

Python内存空对象

2010-05-13 00:03:44

2011-05-29 17:04:10

笔记本体验

2024-04-19 16:58:17

人工智能AI机器人

2009-09-04 11:06:06

Linux桌面Linux操作系统linux

2020-06-12 09:20:33

前端Blob字符串

2020-07-28 08:26:34

WebSocket浏览器

2022-04-30 19:22:35

Python编程语言

2016-01-08 14:23:55

2012-03-23 10:27:08

触屏手机点击区域

2018-02-07 08:21:42

点赞
收藏

51CTO技术栈公众号