Suppose I have a c++ class with a private variable, x. For it's setter, is there any difference using this
? Is there the potential for unwanted / unexpected behavior is I don't use this
?
Setter:
void setX(double input)
{
x = input;
}
Setter using this
:
void setX(double x)
{
this->x = x;
}
These two code fragments (assuming they're inline member functions, since there's no ClassName::
bit) are exactly equivalent. Use whichever you prefer. I would tend to recommend against naming parameters the same as member variables though; it's too easy get them mixed up.
Because of two-phase lookup for class templates, this
might be required to
(see the first example) Both are equivalent.
In a non-template situation, you usually avoid using this
; the generated code will be the same, thus there won't be any difference (see the second example).
The reason for this is that the compiler will try to lookup every symbol it sees. The first place to lookup is in class-scope (except for block and function scope). If it finds a symbol of that name there, it will emit this
implicitly. In reality, member functions are just ordinary functions with an invisible parameter.
class Foo {
void foo () { x = 0; }
void bar () const { std::cout << x; }
void frob();
int x;
};
void Foo::frob() {}
Is actually transformed into
class Foo {
int x;
};
inline void foo (Foo *const this) { this->x = 0; }
inline void bar (Foo const * const this) { std::cout << this->x; }
void frob (Foo * const this) {}
by the compiler.
Behavioral example for this
in templates:
#include <iostream>
void foo() {
std::cout << "::foo()\n";
}
template <typename>
struct Base {
void foo() const { std::cout << "Base<T>::foo()\n"; }
};
template <typename T>
struct Derived_using_this : Base<Derived_using_this<T> > {
void bar() const { this->foo(); }
};
template <typename T>
struct Derived_not_using_this : Base<Derived_not_using_this<T> > {
void bar() const { foo(); }
};
int main () {
Derived_not_using_this<void>().bar();
Derived_using_this<void>().bar();
}
Output:
::foo()
Base<T>::foo()
Example assembly for non-template:
With this
:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movl (%rax), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
leave
ret
Without this
:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movl (%rax), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
leave
ret
Verify yourself:
test.cc:
#include <stdio.h> // Don't use this. I just did so for nicer assembly.
class Foo {
public:
Foo () : i(0) {}
void with_this() const { printf ("%d", this->i); }
void without_this() const { printf ("%d", i); }
private:
int i;
};
int main () {
Foo f;
f.with_this();
f.without_this();
}
Run g++ -S test.cc
. You'll see a file named test.s
, there you can search for the function names.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With