Имеет ли значение, если это используется в установщике C ++? - PullRequest
8 голосов
/ 26 сентября 2011

Предположим, у меня есть класс c ++ с закрытой переменной x.Для сеттера, есть ли разница с использованием this?Есть ли вероятность нежелательного / неожиданного поведения, если я не использую this?

Сеттер:

void setX(double input)
{
   x = input;
}

Сеттер с использованием this:

void setX(double x)
{
   this->x = x;
}

Ответы [ 7 ]

5 голосов
/ 26 сентября 2011

Эти два фрагмента кода (при условии, что они являются встроенными функциями-членами, так как нет ClassName:: бита) в точности эквивалентны. Используйте то, что вы предпочитаете. Я бы рекомендовал не называть параметры так же, как переменные-члены; слишком легко смешать их.

4 голосов
/ 26 сентября 2011

Из-за двухфазного поиска шаблонов классов this может потребоваться

  1. явно заявить, что вы имеете в виду члена
  2. из-за правил поиска, компилятор может предположить, что имеется в виду другая сущность, видимая там

(см. Первый пример) Оба эквивалентны.

В не шаблонной ситуации вы обычно избегаете использования 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, в котором вы можете искать имена функций.

2 голосов
/ 26 сентября 2011
void setX(double x)
{
    this->x = x;
}

Если переменная-член x будет скрыта аргументом x, тогда this-> явно требуется для обеспечения назначения правильной переменной.В противном случае это не нужно.

Но я все равно не рекомендую называть ваш аргумент тем же, что и переменная-член.Первый приведенный вами пример имеет меньше подводных камней.

2 голосов
/ 26 сентября 2011

Этот вариант имеет синтаксическое значение, когда используются шаблоны.Тем не менее, это семантически то же самое;вариант this-> просто проясняет, что вы получаете доступ к текущим объектам и избегает потенциальных столкновений.

1 голос
/ 26 сентября 2011

Несмотря на то, что ваш код будет работать, он плохой код и может кого-то сбить с толку.

Намного лучше дать параметру "setX ()" другое имя.

например

void setX(double new_x)
{
   x = new_x;
}
1 голос
/ 26 сентября 2011

Разницы между ними нет.

0 голосов
/ 26 сентября 2011

Не имеет значения.Я работал с соглашениями о коде, утверждая, что все частные переменные должны быть доступны через this , чтобы сделать код более читабельным.Но кроме читабельности, я не думаю, что есть какая-то разница.

...