198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
1

указатель this что именно он делает

25.05.2013, 15:32. Показов 3746. Ответов 28
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Вот код:

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
 
class test_class
{
public:
void set_var(int a, int b) { varOne = a; varTwo = b; }
test_class operator++() { varOne++; varTwo++; return *this; }
int get_varOne() { return varOne; }
int get_varTwo() { return varTwo; }
    
private:
int varOne;
int varTwo;
};
 
int main()
{
test_class qwerty;
qwerty.set_var(0,10);
    
std::cout << "varOne: " << qwerty.get_varOne() << "\n";
std::cout << "varTwo: " << qwerty.get_varTwo() << "\n";
 
qwerty++;
std::cout << "varOne: " << qwerty.get_varOne() << "\n";
std::cout << "varTwo: " << qwerty.get_varTwo() << "\n";
qwerty++;
std::cout << "varOne: " << qwerty.get_varOne() << "\n";
std::cout << "varTwo: " << qwerty.get_varTwo() << "\n";
        
system("pause");
return 0;
}


Много прочитал про оператор this, но все же осталось смутное представление о нем, думаю на практике, на примере, удастся понять до конца, подскажите, в строчке 7 часть кода: return *this куда именно и что именно возвращает оператор return ?

Правильно ли я понимаю, что return *this возвращает новое значение двух переменных (varOne и varTwo), по тому адресу, по которому они находятся? в объекте qwerty?
т.е. сначала они ( переменные varOne и varTwo) были 0 и 10, и находились по адресам, допустим varOne - 00001, varTwo - 00002, после выполнения операции инкремента, в эти адреса (00001 и 00002) return *this возвращает новые значения, 1 и 11?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.05.2013, 15:32
Ответы с готовыми решениями:

обьясните что именно делает функция this
Обьяснте пожалуйста что делает функция this?

Объясните что именно делает функция даном коде
Помогите пожалуйста. Я не могу понять что делает функция которая стоит вначале моего кода, точнее я...

Объясните что именно делает "x%d, y%d: " или что это в даном коде
#include &lt;iostream&gt; #include &lt;cmath&gt; using namespace std; double rast(double x1, double y1,...

объясните что именно делает функция
Добрый час ! имеется следующий набор функций. не совсем понятен конечный результат. к примеру...

28
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
25.05.2013, 15:47 2
Цитата Сообщение от VLK Посмотреть сообщение
Много прочитал про оператор this
this - не оператор, а указатель. Хранит адрес объекта, метод которого вызван.
* - оператор разыменования указателя, т.е. получения значения, на которое он указывает.

В данном случае в this находится адрес объекта qwerty.
Смотрим на объявление метода:
Цитата Сообщение от VLK Посмотреть сообщение
C++
1
test_class operator++()
Следовательно, оператор ++ вернет новый объект типа test_class.

Добавлено через 59 секунд
Ведь в 8 и 9 строках оператор return почему-то не вызывает вопросов?
0
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
25.05.2013, 16:04  [ТС] 3
Цитата Сообщение от 0x10 Посмотреть сообщение
this - не оператор, а указатель.
Блин, только вчера нашел 2 темы на этом форуме, в обоих писалось что это не оператор, и я все равно на косячил в тексте, ну я имел ввиду указатель.


Цитата Сообщение от 0x10 Посмотреть сообщение
Ведь в 8 и 9 строках оператор return почему-то не вызывает вопросов?
Да, не вызывает, там всё куда проще, есть переменная, оператор return возвращает эту переменную, тут надо быть очень тугим, что бы этого не понимать, а вот что значит return *this что за *this, я все таки до конца не понимаю это для меня тоже самое что:

C++
1
2
int varOne=5;
return varTwo;
при том что varTwo нет, оно не объявлено.


Цитата Сообщение от Olivеr Посмотреть сообщение
del
Меня надо удалить с форума? за что? за то, что я подрываю его своей бездарностью?


Цитата Сообщение от 0x10 Посмотреть сообщение
новый объект
А как понять новый, что за новый? Речь идет о том, что при манипуляциях с объектом класса test_class в данном случае это qwerty будет создана его копия и именно этой копию он вернет, включая новые значения переменных? или как?
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
25.05.2013, 16:13 4
Цитата Сообщение от VLK Посмотреть сообщение
Меня надо удалить с форума? за что?
Там был пост, который автор посчитал нужным удалить.

На самом деле, я предлагаю на секунду отойти от конкретно оператора инкремента, ибо в данном случае это еще больше запутает. Давайте напишем просто метод и назовем его inc, чтобы не огрести лишних забот.
0
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
25.05.2013, 16:15  [ТС] 5
Цитата Сообщение от 0x10 Посмотреть сообщение
Там был пост, который автор посчитал нужным удалить.

На самом деле, я предлагаю на секунду отойти от конкретно оператора инкремента, ибо в данном случае это еще больше запутает. Давайте напишем просто метод и назовем его inc, чтобы не огрести лишних забот.
ладно, сейчас напишу другую программу, которая будет просто прибавлять 5, надеюсь об этом идет речь.
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
25.05.2013, 16:32 6
Вот этот код понятен?
C++
1
2
3
4
5
6
7
8
9
10
11
int main()
{
   int n = 10;
   int* pn = &n;
   int m = *pn;
 
   std::cout << "n = " << n << " at " << &n << std::endl;
   std::cout << "m = " << m << " at " << &m << std::endl;
 
    return 0;
}
Конкретно - строка 5.

Добавлено через 13 минут
В следующем приближении разыменование может происходить в функции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int value_of(int* const p)
{
    // допустим тут что-то осмысленное
    return *p;
}
 
int main()
{
   int n = 10;
   int* pn = &n;
   int m = *pn;
   int k = value_of(&n);
 
   std::cout << "n = " << n << " at " << &n << std::endl;
   std::cout << "m = " << m << " at " << &m << std::endl;
   std::cout << "k = " << m << " at " << &k << std::endl;
 
    return 0;
}
По сути ничего не изменилось и тут вроде очевиднее что берется и куда возвращается.
0
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
25.05.2013, 16:33  [ТС] 7
Строка 3 - объявляется и инициализируется переменная n
Строка 4 - создается указатель *pn и адрес куда ведет этот указатель такой же как и у перемененной n, а точнее оба эти значения (10) находятся по одному адресу.
Строка 5 - объявляется новая переменная m и она инициализируется, ей присваивается значение указателя *pn т.е. 10, при этом она имеет свой адрес в памяти (отдельный от n / *pn)
0
Неэпический
18099 / 10685 / 2061
Регистрация: 27.09.2012
Сообщений: 26,895
Записей в блоге: 1
25.05.2013, 16:38 8
Цитата Сообщение от VLK Посмотреть сообщение
а точнее оба эти значения (10) находятся по одному адресу.
Это одно значение.
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
25.05.2013, 16:42 9
Цитата Сообщение от VLK Посмотреть сообщение
Строка 5 - объявляется новая переменная m и она инициализируется, ей присваивается значение указателя *pn т.е. 10, при этом она имеет свой адрес в памяти (отдельный от n / *pn)
Ну т.е. есть понимание, что в данном случае имеем два разных объекта. Т.е. в m копируется значение ячейки, на которую указывает pn. Ниже написал еще функцию - там происходит то же самое. С return *this - аналогично.
0
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
25.05.2013, 16:50  [ТС] 10
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
int value_of(int* const p)
{
    return *p;
}
 
int main()
{
   int n = 10;
   int* pn = &n;
   int m = *pn;
   int k = value_of(&n);
 
   std::cout << "n = " << n << " at " << &n << std::endl;
   std::cout << "m = " << m << " at " << &m << std::endl;
   std::cout << "k = " << m << " at " << &k << std::endl;
 
   system("pause");
    return 0;
}
В строке 13 мы передаем в функцию адрес переменной n, в строке 3 инициализируется новый указатель *p и ему сразу же присваивается то значение, которое расположено по адресу переменной n, а точнее у них одно значение и расположено оно по одному адресу, а возвращает эта функция уже конкретное число, которое присваивается переменной k, которая имеет свой адрес, отдельный от n и *p.
И если мы находясь в функции изменим значение *p допустим на 20, то значение переменной n тоже изменится на 20.
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
25.05.2013, 17:00 11
Цитата Сообщение от VLK Посмотреть сообщение
указатель *p и ему сразу же присваивается то значение, которое расположено по адресу переменной n
Он на то и указатель, чтобы хранить не значение а только адрес. Не более того.

Добавлено через 1 минуту
Вроде особых затруднений не наблюдаю. Или остались еще вопросы?

Добавлено через 5 минут
Ну докину еще код для размышлений
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct test
{
    int v;
};
 
test inc(test* const this_, int inc_value)
{
    test rv = *this_;
    this_->v += inc_value;
    return rv;
}
 
int main()
{
    test a;
    a.v = 10;
 
    test b = inc(&a, 1);
 
    std::cout << "a.v = " << a.v << std::endl;
    std::cout << "b.v = " << b.v << std::endl;
 
    return 0;
}
2
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
25.05.2013, 17:08  [ТС] 12
Цитата Сообщение от 0x10 Посмотреть сообщение
Вроде особых затруднений не наблюдаю. Или остались еще вопросы?
Мне надо некоторое время что бы переварить
Я напишу тогда попозже.

Добавлено через 7 минут
И надо кодом как раз подумаю
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
25.05.2013, 18:15 13
VLK, перегрузка оператора инкремента - не самый удачный пример для понимания, что такое this.
this это указатель на экземпляр класса (переменную типа определяемого классом) для которого вызывается функция класса (не дружественный и не статический метод определённый в классе).
Что касается оператора ++, то у Вас не определён тип возврата. Для префиксного:
C++
1
2
3
4
ClassName& operator++(){//возвращается ссылка
fieldToInk++;
return *this;//возвращается ссылка на вызывающий экземпляр (на себя) и никакой копии не нужно
}
хотя работать будет и так:
C++
1
2
3
ClassName operator++(){//возврат не ссылка (как говорят люди опытные)))
fieldToInk++;
return *this;//возвращается даже не просто объект типа, содержащий  значение которое будет присвоено вызвавшему экземпляру, а при разименовании получается всё равно ссылка на себя, то есть налицо лишняя операция присвоения *this=*this. И ананимная копия для этого создаётся. То есть первый вариант правильнее.
А вот для постфиксного оператора тип возврата, - только тип класса:
C++
1
2
3
4
5
ClassName operator++(int){
ClassName noInkObjToReturn(*this);//сохранили в объекте состояние до инкремента
fieldToInk++;//инкрементировали в вызывающем(this)
return noInkObjToReturn;//возвращается ссылка на объект типа
}
т.к. для постфиксного нужно увеличить после использования в месте инкрементирования.
1
Evg
Эксперт CАвтор FAQ
21280 / 8303 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.05.2013, 18:37 14
На всякий случай подкину ссылок. Там сумбур, но может что-то полезное сумеешь понять:

После компиляции VS2008 падает после удаления узла дерева, имеющего потомка
После компиляции VS2008 падает после удаления узла дерева, имеющего потомка
чем отличается вызов объекта через "." и через "->"
2
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
25.05.2013, 19:27 15
Evg, хорошие ссылки, спасибо. Последнюю время от времени перечитываю. Речь в них идёт о доступе к членам через класс или его экземпляр. В последней теме не прозвучало, что создатель языка пытался предоставить альтернативу с-шному синтаксису даже для объявлений указателя, чтобы избежать интерпретации изнутри вправо а потом влево:
int *a;// * - указатель а, - имя, int - указывающий на int
вроде такого:
a -> int;
не поручусь за точность, но как-то так. То есть a это указатель на int.
Второй идеей была мысль избежать разноупотребления * в объявлениях и в разыменовании. При этом для совместимости, старый синтаксис оставался в силе. Этой идее не суждено было сбыться и возможно к лучшему. Но как оператор доступа стрелка прижилась. Конечно это для самодокументируемости (понятности) языка. Чтобы различать доступ через экземпляр и через указатель при чтении.
В этом топике, вопрос если я понял о скрытом указателе для функций членов. Он передается как скрытый аргумент и подставляется для имен членов внутри:
myField
this->myField
myFoo()
this->myFoo
а для операторов (бинарных) укзателем является указатель на вызывающий не через оператор доступа "." или "->", а по расположению слева. Если справа нужно, то там через друзей и значит явно через аргументы.
0
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
26.05.2013, 00:06  [ТС] 16
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
 
class test
{
public:
int v;
};
 
test inc(test* const this_, int inc_value)
{
test rv = *this_;
this_->v += inc_value;
return rv;
}
 
int main()
{
test a;
a.v = 10;
 
test b = inc(&a, 1);
 
std::cout << "a.v = " << a.v << std::endl;
std::cout << "b.v = " << b.v << std::endl;
 
system("pause");
return 0;
}

Строчки 3-7 объявляется класс test, у него одна открытая переменная "v".


в Строчке 18 объявляется объект "a" класса "test", и переменной "v" присваивается значение 10.

в Строчке 21 объявляется еще один объект "b" класса "test", и ему присваивается значение которое рассчитывается в функции строчки 9-14

В строчке 9 объявляется функция "inc" типа "test", с параметрами, 1. параметр это ссылка на объект "a" класса "test", второй целочисленное число.

В строке 11 объявляется объект "rv" класса "test", все его параметры равны параметрам this_, а в свою очередь его параметры равны объекту "a" класса "test", this_ это ссылка на объект "a", Но объект "rv" имеют свой адрес в области памяти, отличный от "a", а "test* const this_" и "a" имеют один адрес в области памяти.

В строке 12 к "v" через указатель прибавляется "inc_value", но эта "v" имеет отношение к "test* const this_" из строчки 9, а не к объекту "rv"

т.е. 12 строчка поменяла значение "a.v" на 11
При это "b.v" остается 10 т.к. он имеет разный адрес в памяти от "a.v" и "test* const this_"

Все правильно?

и еще вопрос насчет строчки 13, на сколько мне известно оператор return возвращает только значение, число или лог. значение, а тут получается объект класса, я может не в полном объеме понимаю

Я представляю так? вернуть можно значение, например:

int x=10;
return x;

а тут, для меня это равнозначно:

return funciya();
или
return int x;

но так же не может быть, где ошибка в моей логике?
0
~ Эврика! ~
1257 / 1006 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
26.05.2013, 00:20 17
Цитата Сообщение от VLK Посмотреть сообщение
т.е. 12 строчка поменяла значение "a.v" на 11
При это "b.v" остается 10 т.к. он имеет разный адрес в памяти от "a.v" и "test* const this_"

Все правильно?
b остался таким потому, что вы ему присвоили старое значение a, которое вернулось из функции, где вы его вначале скопировали через переданный указатель в локальную переменную.

Цитата Сообщение от VLK Посмотреть сообщение
и еще вопрос насчет строчки 13, на сколько мне известно оператор return возвращает только значение, число или лог. значение, а тут получается объект класса, я может не в полном объеме понимаю
Всё правильно. Функции возвращают значения. Объекты класса тоже могут быть значениями. Главное свойство значений: их можно копировать (иногда ещё присваивать можно). Поэтому у объектов-значений должен быть конструктор копирования, чтобы они вели себя как значения. В том числе чтобы они возвращались из функций. Конструктор копирования обязательно существует у каждого класса; если не явно написанный вами, то сгенерированный компилятором автоматически (однако его использование может быть запрещено или ограничено). Автоматически сгенерированный тупо копирует все поля из одного объекта в другой. Кроме того, иногда функции должны не возвращать копию объекта, а создать объект где-то вне функции. В Си++ для этого ввели специальную приблуду rvalue, а до этого перебивались out-параметрами, оптимизациями компилятора или писали объекты (или обёртки) так, чтобы не было разницы между копированием и перемещением объекта.
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
26.05.2013, 00:37 18
VLK, то что делает функция inc лучше сделать по-другому. Перегрузите постфиксный оператор operator++()
тогда:
C++
1
2
3
4
5
6
7
8
9
10
int main()
{
test a;
a.v = 10;
test b =a++;
std::cout << "a.v = " << a.v << std::endl;
std::cout << "b.v = " << b.v << std::endl;
system("pause");
return 0;
}
результат тот же, но достигается обычным путём. При возврате ссылки из пост-инкрементного ++, разыменование указателя this не меняет адрес вызывающего объекта, то есть нет нужды передавать константный указатель.
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
26.05.2013, 07:50 19
IGPIGP, я специально ушел от оператора к функции, чтобы не заморачиваться с префиксной и постфиксной формами и не запутывать еще и ссылками. (Да, выше верно было сказано, что пример инкремента далеко не самый удачный)

Добавлено через 9 минут
Цитата Сообщение от VLK Посмотреть сообщение
В строчке 9 объявляется функция "inc" типа "test", с параметрами, 1. параметр это ссылка на объект "a" класса "test", второй целочисленное число.
Функция inc, которая возвращает объект типа test. Сигнатура функции состоит из двух параметров: константный указатель на объект класса test и целое со знаком.

Цитата Сообщение от VLK Посмотреть сообщение
"test* const this_" и "a" имеют один адрес в области памяти.
this_ и a расположены по разным адресам. При этом в указателе this содержится адрес объекта 'a'.
2
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
26.05.2013, 10:49 20
Цитата Сообщение от 0x10 Посмотреть сообщение
ушел от оператора к функции, чтобы не заморачиваться с префиксной и постфиксной формами и не запутывать
0x10, совершенно согласен. Я разлил воду именно поэтому. В исходном примере [TC] не указал тип возврата, для оператора и это говорит, что вопрос как возвращается разименованный указатель, - за скобками. Но без этого пример ещё более неудачен, даже не учитывая, что инкремент это оператор-выражение, сочетающее lvalue, rvalue и присваивание. Ну то есть очень неудачный пример для понимания this.

Добавлено через 7 минут
Цитата Сообщение от IGPIGP Посмотреть сообщение
Но как оператор доступа стрелка прижилась.
неправильная конструкция, не прижилась, а осталась!( Она была в С-структурах при доступе через указатель.)

Не по теме:

перечитываю написанное и удивляюсь :swoon:

0
26.05.2013, 10:49
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.05.2013, 10:49
Помогаю со студенческими работами здесь

Прокомментируйте отрывок кода, что именно он делает
Дан следующий кодConsole.Write(&quot;Введите m:&quot;); int m =...

Как именно в методах расширения указать, что переходить нужно именно главный контроллер?
В проекте есть несколько Areas. Маршрутизация нстроена так (для наглядности сократил) public...

Инициализация делает указатель из целого числа
Выдает ошибку на мой указатель, может я не правильно объявил указатель COORD goRight(COORD pk,...

Нюансы синтаксиса: что означает указатель на указатель?
//Как работает 6 строчка? #include &lt;iostream&gt; using namespace std; int main( void ) { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru