You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++类构造函数中this指针与作用域运算符赋值的差异及优劣

关于C++构造函数中this->和::访问成员变量的差异、效率与规范问题

我最近重新捡起来学C++,写类构造函数的时候发现两种给成员变量赋值的写法——用this->和用类名加::,而且居然都能跑起来?之前上学的时候只学过this->的用法,现在有点懵,想搞清楚这俩到底有啥不一样,哪种更靠谱、效率更高,还有底层到底是怎么执行的。

先贴一下我的代码:

// cPerson.h
#pragma once
class cPerson {
public:
    cPerson();
    ~cPerson();
    int Age;
};
// cPerson.cpp
#include "cPerson.h"
cPerson::cPerson() {
    this->Age = 3; // Way 1
    cPerson::Age = 4; // Way 2
}
cPerson::~cPerson() {
}

首先得先纠正一个误区:你的代码里Way2的写法其实是不符合C++标准的!Age是类的非静态成员变量,它属于每个对象实例,必须通过具体的对象来访问,而类名::成员名这个语法,标准上只能用来访问静态成员、类的嵌套类型,或者子类中被覆盖的基类成员。有些编译器(比如MSVC)可能会开个后门允许这种非标准写法,但这是不具备可移植性的,换个编译器(比如GCC)大概率会直接报错,而且逻辑上也说不通——你总不能修改一个不属于任何对象的“全局Age”吧?

接下来咱们分合法的场景聊清楚两者的差异:

一、核心差异:适用场景完全不同

  • this->成员名:this是指向当前调用成员函数的对象实例的指针,this->Age就是明确访问当前对象自己的Age成员。这种写法适用于所有非静态成员的访问,尤其当成员名和函数的局部变量/参数名重名时,能清晰区分(比如构造函数参数是int Age,this->Age = Age;就不会混淆)。
  • 类名::成员名:这个语法是给静态成员准备的——静态成员属于整个类,不属于任何对象,所以用类名直接访问才是合理的。比如如果Age是静态成员static int Age;,那cPerson::Age =4;就是完全合法的写法,能明确告诉读者:这是个类级别的变量,和单个对象没关系。

二、效率对比:合法场景下各有千秋

  • 对于非静态成员的this->Age:编译后,this是成员函数的隐式参数(x86下通常存在ECX寄存器,x64是RCX),访问成员就是通过this指针加上成员在类中的内存偏移量,找到具体地址后写入值——是一次间接内存访问,效率没问题,是C++的标准操作。
  • 对于静态成员的cPerson::Age:静态成员在程序启动时就存在全局/静态存储区,地址是编译时就确定的,访问它是直接读写固定内存地址,甚至可能被编译器优化到寄存器里,不需要依赖this指针,效率略高一点(但日常开发中这点差异基本可以忽略)。
  • 至于你代码里的非标准cPerson::Age:编译器其实会偷偷把它转换成this->Age来执行,所以效率和Way1完全一样,但写法不合法,没必要用。

三、编码规范:怎么写才专业

  • 访问非静态成员:优先用this->成员名(或者如果没有命名冲突,直接写成员名也可以)。this->的好处是一眼就能看出这是类的成员变量,避免和局部变量混淆,可读性拉满。绝对别用类名::非静态成员这种野路子写法,坑自己也坑队友。
  • 访问静态成员:优先用类名::静态成员,这样能明确体现它的静态属性,比用this->静态成员清晰多了——毕竟静态成员和对象无关,用this->会误导读者以为它和当前对象有关系。

四、底层执行逻辑:内存和CPU层面到底咋跑的

1. this->Age的执行流程

C++的非静态成员函数,编译器都会偷偷给它加一个隐式参数this,指向调用这个函数的对象。比如你的构造函数cPerson::cPerson(),实际编译后的函数签名大概是void cPerson_cPerson(cPerson* this)。

当执行this->Age =3;时:

  • CPU会从寄存器(比如ECX)里拿到this指针的值,也就是当前对象的内存地址。
  • Age作为非静态成员,在类的内存布局里有固定的偏移量(比如你的类只有Age,偏移量就是0)。
  • CPU计算出this + 偏移量的地址,也就是Age的具体内存位置,然后把3写入这个地址。

2. 类名::静态成员的执行流程

静态成员变量在程序加载时就被分配到全局/静态存储区,它的内存地址是编译阶段就确定好的。

假设Age是静态成员,执行cPerson::Age=4;时:

  • CPU直接使用编译时确定的静态成员地址,把4写入进去,全程不需要this指针,也不需要依赖任何对象实例。

总结一下:你的代码里Way2是编译器的非标准扩展,别用。正常开发中,非静态成员用this->(或直接写),静态成员用类名::,这才是符合标准、可读性高的写法。

内容的提问来源于stack exchange,提问作者Phillip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:56:52