C++类构造函数中this指针与作用域运算符赋值的差异及优劣
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

