使用“this”指针是否在运行时向程序添加了另一个操作?
举一个例子来更好地解释这个问题:
class C
{
public:
void set_x(int val){ x = val; }
void set_this_x(int val){ this->x = val; }
private:
int x;
};
在运行时,函数“C :: set_x()”是否比“C :: set_this_x()”执行少1次操作?
谢谢! : - )
答案 0 :(得分:19)
两个成员函数之间没有区别。它必须是,因为这是C ++标准(ISO / IEC 14882:2003)所说的:
9.3.1非静态成员函数[class.mfct.nonstatic]
2. 当
id-expression
(5.1)不属于班级成员时 访问语法(5.2.5)并且不用于形成指向成员的指针(5.3.1) 用于类X
或类的非静态成员函数体中 在mem-initializer
中用于类X
的构造函数,如果是name lookup(3.4.1)将id-expression
中的名称解析为非静态名称 类X
的非类型成员或X
的基类,id-expression
转换为类成员访问表达式 (5.2.5)使用(*this)
(9.3.2)作为左侧的后缀表达式.
运算符。然后成员名称引用该成员 调用该函数的对象。5.2.5班级成员访问[expr.ref]
3. 如果
E1
的类型为“指向类X
的指针”,那么表达式E1->E2
转换为等效格式(*(E1)).E2;
...
这意味着以下代码:
class C
{
public:
void set_x(int val) { x = val; }
void set_this_x(int val) { this->x = val; }
private:
int x;
};
将根据9.3.1 / 2和5.2.5 / 3转换为以下代码:
class C
{
public:
void set_x(int val) { (*this).x = val; } // as per 9.3.1/2
void set_this_x(int val) { (*(this)).x = val; } // as per 5.2.5/3
private:
int x;
};
为了表明确实没有区别,至少对于一个编译器,这里是VC ++编译器发出的C::set_x()
和C::set_this_x()
函数的反汇编的并排比较,禁用了优化(/Od
):
void set_x(int val){ x = val; } void set_this_x(int val){ this->x = val; }
push ebp push ebp
mov ebp,esp mov ebp,esp
sub esp,0CCh sub esp,0CCh
push ebx push ebx
push esi push esi
push edi push edi
push ecx push ecx
lea edi,[ebp-0CCh] lea edi,[ebp-0CCh]
mov ecx,33h mov ecx,33h
mov eax,0CCCCCCCCh mov eax,0CCCCCCCCh
rep stos dword ptr es:[edi] rep stos dword ptr es:[edi]
pop ecx pop ecx
mov dword ptr [ebp-8],ecx mov dword ptr [ebp-8],ecx
mov eax,dword ptr [this] mov eax,dword ptr [this]
mov ecx,dword ptr [val] mov ecx,dword ptr [val]
mov dword ptr [eax],ecx mov dword ptr [eax],ecx
pop edi pop edi
pop esi pop esi
pop ebx pop ebx
mov esp,ebp mov esp,ebp
pop ebp pop ebp
ret 4 ret 4
请注意,编译器会为两个成员函数生成完全相同的程序集。
答案 1 :(得分:9)
不,它不会产生运行时差异,它只是语法。仍然在第一个函数中访问this
指针,它只是隐式指定而不是显式指定。
顺便说一句,这有点像过早的优化 - 先编写干净的代码,然后再编写快速的代码。
答案 2 :(得分:6)
如果从类模板继承,则需要this->member
语法:
template<typename T>
class Base
{
protected:
T x;
};
template<typename T>
class Derived : Base<T>
{
public:
void whatever()
{
T a = x; // error
T b = this->x; // ok
}
};
答案 3 :(得分:3)
不,没有区别
当你直接引用一个成员时,编译器实际上是通过this
来取消它。
答案 4 :(得分:3)
它是一样的。但是,在某些情况下,“this”可用于消除歧义。
class C
{
public:
void set_x(int x){ x = x; } // does nothing
void set_this_x(int x){ this->x = x; } // sets the variable
private:
int x;
};
答案 5 :(得分:2)
没有。
如果你在某人的代码中偶然发现了这个表达,那么它可能起源于这样:
struct A
{
int x;
void set_X(int x)
{
this->x = x;
}
};
答案 6 :(得分:2)
没有区别,编译器已经自动为此生成代码 - &gt;虽然它是多余的语法,但有两个很好的理由使用它:
使用支持自动完成的编辑器。当您键入“this-&gt;”时,编辑器会弹出一个工具窗口,其中显示可供选择的班级成员列表。这可以加快输入速度,并有助于避免因输入错误而导致的错误编译错误。
它有助于避免不得不提出人工参数名称。您可以为参数赋予与类成员相同的名称:void set_x(int x){this-&gt; x = x; }。
答案 7 :(得分:2)
你可以说foo
代替this->foo
只是语法糖。编译代码没有区别。像所有的语法糖一样,一小部分人都在谴责它,但最喜欢它。要了解您在问题上的立场,请尝试使用不提供此语法糖的perl或python等语言。 Python代码充满了self.foo
;在perl OO代码中,您将看到self->foo
遍布整个地方。它可能有点分散注意力。
答案 8 :(得分:1)
重要的一点是当你给一个与类成员同名的局部变量时。例如:
class Example {
public:
int something();
int somethingElse();
}
int Example::somethingElse() {
int something = something(); // ERROR
int something = this->something(); // OK
// ...
}