Из-за двухфазного поиска шаблонов классов this
может потребоваться
- явно заявить, что вы имеете в виду члена
- из-за правил поиска, компилятор может предположить, что имеется в виду другая сущность, видимая там
(см. Первый пример) Оба эквивалентны.
В не шаблонной ситуации вы обычно избегаете использования this
; сгенерированный код будет таким же, поэтому не будет никакой разницы (см. второй пример) .
Причина этого в том, что компилятор попытается найти все символы, которые он видит. Первое место для поиска находится в области видимости класса (за исключением области блока и функции). Если он найдет символ этого имени там, он испустит this
неявно. В действительности функции-члены - это просто обычные функции с невидимым параметром.
class Foo {
void foo () { x = 0; }
void bar () const { std::cout << x; }
void frob();
int x;
};
void Foo::frob() {}
На самом деле превращается в
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) {}
компилятором.
Поведенческий пример для this
в шаблонах:
#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();
}
Выход:
::foo()
Base<T>::foo()
Пример сборки для не-шаблона:
С 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
Без 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
Проверьте себя:
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();
}
Выполнить g++ -S test.cc
. Вы увидите файл с именем test.s
, в котором вы можете искать имена функций.