Is there a difference between using "this" pointer and not using it?
Does using "this" pointer adds another operation to the program at runtime?
Just to give an example to explain the question better:
clas开发者_运维百科s C
{
public:
void set_x(int val){ x = val; }
void set_this_x(int val){ this->x = val; }
private:
int x;
};
Does the function "C::set_x()", during runtime, performs 1 less operation than "C::set_this_x()" ?
Thanks! :-)
There is no difference between the two member functions. It has to be, since this is what the C++ Standard (ISO/IEC 14882:2003) has to say:
9.3.1 Nonstatic member functions [class.mfct.nonstatic]
2. When an
id-expression
(5.1) that is not part of a class member access syntax (5.2.5) and not used to form a pointer to member (5.3.1) is used in the body of a nonstatic member function of classX
or used in themem-initializer
for a constructor of classX
, if name lookup (3.4.1) resolves the name in theid-expression
to a nonstatic nontype member of classX
or of a base class ofX
, theid-expression
is transformed into a class member access expression (5.2.5) using(*this)
(9.3.2) as the postfix-expression to the left of the.
operator. The member name then refers to the member of the object for which the function is called.5.2.5 Class member access [expr.ref]
3. If
E1
has the type “pointer to classX
,” then the expressionE1->E2
is converted to the equivalent form(*(E1)).E2;
...
So that means the following code:
class C
{
public:
void set_x(int val) { x = val; }
void set_this_x(int val) { this->x = val; }
private:
int x;
};
would've been transformed to the following code according to 9.3.1/2 and 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;
};
To show that there really is no difference, at least for one compiler, here's a side-by-side comparison of the disassembly of the C::set_x()
and C::set_this_x()
function the VC++ compiler emits with optimizations disabled (/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
Note that the compiler produces the exact same assembly for both member functions.
No, it doesn't make a runtime difference, it's just syntax. The this
pointer is still accessed in the first function, it's only specified implicitly instead of explicitly.
By the way, this smells like a premature optimization - write clean code first, fast code later.
The this->member
syntax is required if you inherit from a class template:
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
}
};
No, there is no difference.
when you refer a member directly, the compiler actually derefers it through the this
.
It's the same. However, "this" can be used to disambiguate in certain cases.
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;
};
No.
If you stumbled over that expression in someone's code, it's probably originated in something like this:
struct A
{
int x;
void set_X(int x)
{
this->x = x;
}
};
No difference, the compiler already automatically generates code for this-> While it is superfluous syntax, there are two good reasons to use it:
using an editor that supports auto-completion. When you type "this->", the editor pops up a tool window that presents a list of class members to choose from. This can speed up typing and helps avoid silly compile errors due to typing mistakes.
it helps avoiding having to come up with artificial argument names. You can give the argument the same name as the class member: void set_x(int x) { this->x = x; }.
That you can say foo
instead of this->foo
is just syntactic sugar. There is no difference in the compiled code. Like all syntactic sugar, a small handful decry it but most love it. To see where you stand on the issue, try using a language like perl or python that doesn't provide this syntactic sugar. Python code is peppered with self.foo
; in perl OO code you'll see self->foo
all over the place. It can be a bit distracting.
One of the times it matters is when you are giving a local variable the same name as a class member. For example:
class Example {
public:
int something();
int somethingElse();
}
int Example::somethingElse() {
int something = something(); // ERROR
int something = this->something(); // OK
// ...
}
精彩评论