Форум программистов, компьютерный форум CyberForum.ru

Передача в функцию - ссылки, указатели, константы - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 21, средняя оценка - 4.67
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
16.06.2013, 23:18     Передача в функцию - ссылки, указатели, константы #1
Вот программа:

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream> 
 
 void fun(int &rhs) 
{
rhs++;
}
 
int main()
{
int var = 2;
        
fun(var);
 
std::cout << var << "\n";
    
system("pause");
return 0;
}


В строке 10 я создаю переменную var и присваиваю ей значение 2, т.е. допустим по адресу 0001 у меня располагается значение 2
В строке 12 я передаю var в виде ссылке в функцию, где она получает новое имя (временное имя, псевдоним) - rhs, значение rhs располагается по тому же адресу что и var - 0001.
В строке 5 я прибавляю 1 к rhs и по адресу 0001 меняется значение с 2 на 3.

по этому в строке 14 мне выведет на экран 3, а не 2.

Вопрос, а что происходит, как работает следующая программа:

Кликните здесь для просмотра всего текста
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 & fun(int rhs) 
{
rhs++;
 
return rhs;
}
 
int main()
{
int varOne = 2;
int varTwo;
        
varTwo = fun(varOne);
 
std::cout << varTwo << "\n";
    
system("pause");
return 0;
}


В частности меня интересует какую роль выполняет оператор & в строке 3 и чем отличается такая же программа без &.

Распишите по возможности так, как я описывал первую программу, что бы не оставалось вопрос, что бы не пришлось переспрашивать.

Это первый вопрос в этой теме, дальше я буду добавлять вопросы, про указатели константы и т.д. так что если что, смотрите последние сообщения, а не первое.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.06.2013, 23:18     Передача в функцию - ссылки, указатели, константы
Посмотрите здесь:

Ссылки или указатели (Написать функцию , которая вычисляет гипотенузу, площадь и периметр прямоугольного треугольника) C++
Указатели и массивы. Передача массива в функцию по указателю C++
как лучше передавать значения в функцию? ссылки vs указатели C++
Ссылки и указатели на функцию C++
Передача в функцию через указатели C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
16.06.2013, 23:31     Передача в функцию - ссылки, указатели, константы #2
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 & fun(int rhs)
{
    rhs++;
 
    return rhs;
}
 
int main()
{
    int varOne = 2; 
    int varTwo;
 
    varTwo = fun(varOne);
 
    std::cout << varTwo << "\n";
 
    system("pause");
    return 0;
}
Когда мы вызываем int& fun(int rhs), то переданный аргумент передается по значению, то есть копируется, то есть создается временный объект rhs (копия переданного) в зоне видимости функции fun. Потом вы увеличиваете значение rhs. Но самое интересное кроется в возвращаемом значении.

C++
1
2
3
4
    int varOne = 2; //переменная, не ссылка
    int varTwo; //переменная, не ссылка
 
    varTwo = fun(varOne); //функция возвращает ссылку, но vatTwo не ссылка, поэтому происходит копирование
Если было бы так:
C++
1
int &vatTwo = fun(vatOne); //ошибка, функция возвращает ссылку на временный объект
В общем случае возвращать ссылку - плохая примета.
xtorne21st
интересующийся
300 / 271 / 19
Регистрация: 25.09.2010
Сообщений: 1,056
16.06.2013, 23:32     Передача в функцию - ссылки, указатели, константы #3
Всё зависит от конкретного компилятора. В стандарте написано, что возврат ссылки на локальный объект приводит к UB.
Кудаив
328 / 405 / 24
Регистрация: 27.05.2012
Сообщений: 1,162
Завершенные тесты: 2
16.06.2013, 23:34     Передача в функцию - ссылки, указатели, константы #4
Цитата Сообщение от VLK Посмотреть сообщение
& в строке 3
означает что функция возвращает ссылку на переменную

Цитата Сообщение от VLK Посмотреть сообщение
чем отличается такая же программа без &.
если бы не было & то функция производила манипуляции с переменной, делала её копию и возвращала к месту вызова
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
16.06.2013, 23:36     Передача в функцию - ссылки, указатели, константы #5
В строке 12 я создаю переменную var и присваиваю ей значение 2, т.е. допустим по адресу 0001 у меня располагается значение 2
В строке 15 я передаю копию var в виде ссылке в функцию, где она получает новое имя (временное имя, псевдоним) - rhs, значение rhs которая (копия) располагается по тому же адресу что 0002.
В строке 5 я прибавляю 1 к rhs (копии var) и по адресу 0002 меняется значение с 2 на 3.
В строке 7 я стреляю себе в ногу возвращаю ссылку на копию var, которая будет уничтожена после выхода из вункции
по этому в строке 15 происходит неопределенное поведение, так как ссылка ссылается на не существующую переменную.
что происходит дальше - на совести разработчиков компилятор, возможно все!
вот и сказочке конец...
Кудаив
328 / 405 / 24
Регистрация: 27.05.2012
Сообщений: 1,162
Завершенные тесты: 2
16.06.2013, 23:38     Передача в функцию - ссылки, указатели, константы #6
Цитата Сообщение от Olivеr Посмотреть сообщение
int &vatTwo = fun(vatOne); //ошибка, функция возвращает ссылку на временный объект

Цитата Сообщение от xtorne21st Посмотреть сообщение
Всё зависит от конкретного компилятора
MinGW - прожевал
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
16.06.2013, 23:40  [ТС]     Передача в функцию - ссылки, указатели, константы #7
Olivеr, т.е. правильно я понимаю что во второй программе грубо говоря происходит не return 3, а return ссылка на rhs (при этом rhs уже нет, т.к. это был временная переменная) ? а уже из этой ссылки varTwo берет значение 3?

извините за колхозное описание ситуации, мне так проще понять.
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
16.06.2013, 23:43     Передача в функцию - ссылки, указатели, константы #8
VLK, если записано
C++
1
int & fun(int rhs)
и
C++
1
varTwo = fun(varOne);
то происходит копирование rhs в переменную varTwo

По крайней мере так в
Цитата Сообщение от Кудаив Посмотреть сообщение
MinGW
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
16.06.2013, 23:44  [ТС]     Передача в функцию - ссылки, указатели, константы #9
Цитата Сообщение от Olivеr Посмотреть сообщение
VLK, если записано
C++
1
int & fun(int rhs)
и
C++
1
varTwo = fun(varOne);
то происходит копирование rhs в переменную varTwo

По крайней мере так в
но rhs при этом уже не существует т.к. функция (fun) закончила свою работу?
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
16.06.2013, 23:50     Передача в функцию - ссылки, указатели, константы #10
VLK, пишу по пунктам как я это вижу:
1. Передаем копию varOne в функцию fun, создается переменная с именем rhs (аналогичная varOne), но они никак не связаны!
2. увеличиваем значение rhs на 1
3. Возвращаем копию rhs и присваиваем ее varTwo, уничтожаем rhs

Добавлено через 1 минуту
Совет: напишите простенькую структуру со всеми конструкторами и деструктором. В их телах выведите на экран сообщение о том, что вызван такой то конструктор/деструктор. И проделайте ту же программу с этой структурой.
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
17.06.2013, 00:02  [ТС]     Передача в функцию - ссылки, указатели, константы #11
Все равно не вижу, не понимаю разницу между
C++
1
int & fun(int rhs)
и
C++
1
int fun(int rhs)
Ладно, завтра продолжу изучение.
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
17.06.2013, 00:10     Передача в функцию - ссылки, указатели, константы #12
Вот код. Запустите и разберетесь.
Кликните здесь для просмотра всего текста
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
 
#define DEBUG
struct Foo
{
    int x;
    explicit Foo(int val = 0): x(val)
    {
        #ifdef DEBUG
        std::cout << "Стандартный/по значению конструктор\n";
        #endif
    }
    Foo(const Foo &obj): x(obj.x)
    {
        #ifdef DEBUG
        std::cout << "Конструктор копирования\n";
        #endif
    }
    Foo& operator = (const Foo &obj)
    {
        if (this == &obj) return *this;
        x = obj.x;
        #ifdef DEBUG
        std::cout << "Оператор присвоения\n";
        #endif
        return *this;
    }
 
    ~Foo()
    {
        #ifdef DEBUG
        std::cout << "Деструктор, x = " << this->x << std::endl;
        #endif
    }
};
 
Foo& GetFoo(Foo f)
{
    ++f.x;
    return f;
}
 
int main()
{
    setlocale(LC_CTYPE, "");
    Foo h(5);
    std::cout << "~Вызов функции...\n";
    Foo g = GetFoo(h);
    std::cout << "~Конец функции...\n";
    std::cout << g.x << std::endl;
    return 0;
}
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
17.06.2013, 17:14  [ТС]     Передача в функцию - ссылки, указатели, константы #13
Кликните здесь для просмотра всего текста
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream> 
 
class mat
{
public:
mat(): zn(0) { setlocale(LC_ALL,""); std::cout << "Конструктор без значения (по умолчанию 0) \n"; }
mat(int rhs): zn(rhs) { setlocale(LC_ALL,""); std::cout << "Конструктор со значением: " << get_zn() << " \n"; }
~mat() { setlocale(LC_ALL,""); std::cout << "Деструктор со значением: " << get_zn() << " \n"; }
mat(const mat & rhs ) { zn = rhs.get_zn(); setlocale(LC_ALL,""); std::cout << "Конструктор копирования со значением: " << get_zn() << " \n";  }
 
void set_zn(int rhs) { zn = rhs; }
int get_zn() const { return zn; }
void show_zn() { std::cout << zn << "\n"; }
 
mat operator= (const mat &rhs)
{
if (this == &rhs)
{ return *this; }
else
{
zn = rhs.get_zn();
return *this;
}
}
 
mat operator+ (const mat &rhs)
{
return (zn + rhs.get_zn());
}
 
mat operator- (const mat &rhs)
{
return (zn - rhs.get_zn());
}
 
private:
int zn;
};
 
mat fun(mat a, mat b)
{
std::cout << "В функции без &..\n";
return a+b;
}
 
mat & link(mat a, mat b)
{
std::cout << "В функции с &..\n";
return a+b;
}
 
 
int main()
{
setlocale(LC_ALL,"");
 
mat var2 = 2;
mat var3 = 3;
mat var5 = 0; 
 
std::cout << "Переходим в функцию без &..\n";
var5 = fun(var2, var3);
std::cout << "Вышли из функции без &..\n";
 
var5.show_zn();
std::cout << "\n *********************************** \n\n";
 
 
mat var7 = 7;
mat var8 = 8;
mat var15 = 0;
 
std::cout << "Переходим в функцию с &..\n";
var15 = link(var7, var8);
std::cout << "Вышли из функции с &..\n";
 
var15.show_zn();
 
system("pause");
return 0;
}


Вот я сделал программу, но все равно до конца не понимаю почему они (функции fun и link) работают по разному.
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
17.06.2013, 17:46     Передача в функцию - ссылки, указатели, константы #14
VLK, еще раз говорю, что в этой функции ошибка:
C++
1
2
3
4
5
mat & link(mat a, mat b)
{
    std::cout << "В функции с &..\n";
    return a+b; //возвращается ссылка на временный объект. после выхода из функции временный объект уничтожится и ссылка будет указывать на непонятно что
}
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
17.06.2013, 19:08  [ТС]     Передача в функцию - ссылки, указатели, константы #15
Это я понимаю, получается что такая запись изначально ошибочная и не должна использоваться вообще, НО - Использование класса String

Вот в строчке 17, 21 используется, этот пример из книги, значит для чего то и как то используется, хотелось бы узнать как и что.

PS кстати данную программу я хотел повторить, половина работает, но не работает строчка1 = строчк2 + строчка3 и я думаю проблема как раз кроется в этих строчках 17 и 21, но я их не понимаю по этому не могу толком найти проблему.
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
17.06.2013, 19:16     Передача в функцию - ссылки, указатели, константы #16
Цитата Сообщение от VLK Посмотреть сообщение
21
Оператор присвоения. Зачем возвращать копию если можно и нужно возвращать ссылку? Объект то, на который ссылается ссылка, существует.

Цитата Сообщение от VLK Посмотреть сообщение
17
Оператор []. Предназначен для получения доступа к элементу последовательности. Почему ссылка? 1. Он существует даже после завершения функции. 2. Что бы работала запись:
C++
1
2
string str = "123";
str[1] = '1'; //113
Думаю очевидно, что str[1] вернет ссылку на char

Цитата Сообщение от VLK Посмотреть сообщение
этот пример из книги
Не все примеры в книгах являются корректными. Многие из них приведены для того что бы объяснить на пальцах почему так делать не стоит.

Цитата Сообщение от VLK Посмотреть сообщение
но не работает строчка1 = строчк2 + строчка3 и я думаю проблема как раз кроется в этих строчках 17 и 21, но я их не понимаю по этому не могу толком найти проблему.
В вашей программе не перегружен оператор +
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
19.06.2013, 13:24  [ТС]     Передача в функцию - ссылки, указатели, константы #17
Я примерно понял что же все же означает эта & в данном случае.

Новый вопрос по данной теме, теперь про константы, подскажите, что делает ключевое слово const и с кем, с чем, в каждом конкретном случае:

1. const int fun (int var) { }
2. int const fun (int var) { }
3. int fun (int var) const { }

4. int fun (const int var) { }
5. int fun (int const var) { }
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
19.06.2013, 13:44     Передача в функцию - ссылки, указатели, константы #18
Цитата Сообщение от VLK Посмотреть сообщение
1. const int fun (int var) { }
2. int const fun (int var) { }
3. int fun (int var) const { }
4. int fun (const int var) { }
5. int fun (int const var) { }
1 и 2 - одно и тоже: возвращают константную копию переменной типа int
3. возвращает копию переменной типа int. указатель this - константый
4 и 5. принимает константную копию переменной типа int и возвращает копию переменной типа int
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
19.06.2013, 13:44     Передача в функцию - ссылки, указатели, константы #19
Цитата Сообщение от VLK Посмотреть сообщение
1. const int fun (int var) { }
2. int const fun (int var) { }
эти две записи означают одно и тоже, возвращение константы, какого-то особого смысла в этом нет
Цитата Сообщение от VLK Посмотреть сообщение
4. int fun (const int var) { }
5. int fun (int const var) { }
эти две записи означают одно и тоже, var внутри функции ведет себя как константа
Цитата Сообщение от VLK Посмотреть сообщение
3. int fun (int var) const { }
такая запись допустима только для методов класса.
означает она то что этот метод класса не модифицирует состояние объекта.
внутри такого метода нельзя модифицировать поля класса, за исключением полей объявленных как mutable.
но эти оганичения можно обойти с помощью const_cast, но если такое потребовалось то вы явноно что-то делаете не так.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.06.2013, 14:20     Передача в функцию - ссылки, указатели, константы
Еще ссылки по теме:

C++ Передача массива в функцию (указатели)
Передача ссылки на массив в функцию C++
Передача ссылки и указателя в функцию C++

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

Или воспользуйтесь поиском по форуму:
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
19.06.2013, 14:20  [ТС]     Передача в функцию - ссылки, указатели, константы #20
Цитата Сообщение от Jupiter Посмотреть сообщение
эти две записи означают одно и тоже, возвращение константы, какого-то особого смысла в этом нет
т.е., вот есть небольшая программа:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream> 
 
int const fun  ( int  D) 
{
D = 8;
return D;
}
 
int main()
{
int varOne = 5;
int varTwo = 0;
 
varTwo = fun(varOne);
 
std::cout << varTwo << "\n";
 
system("pause");
return 0;
}

Есть 2 переменных - varOne, допустим она находится по адресу 0001 и varTwo которая находится по адресу 0002, когда начинается выполнение функции (fun) то мы создаем копию переменной varOne, имя этой копии D и располагается она по адресу 0003, и то, что мы возвращаем является константным значением, т.е. переменная расположенная по адресу 0003 является константной, но она становится константной только тогда когда мы ее возвращаем, т.е. до строчки 6 (return D) я могу с этим D делать все что угодно, а далее, в строчках 7 и 14 переменная расположенная в 0003 является константной, соответственно после строчки 14 переменная по адресу 0003 будет уничтожена, по этому данная запись бесполезна?

Цитата Сообщение от Jupiter Посмотреть сообщение
эти две записи означают одно и тоже, var внутри функции ведет себя как константа
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream> 
 
int fun  (int const  D) 
{
D = 8;
return D;
}
 
int main()
{
int varOne = 5;
int varTwo = 0;
 
varTwo = fun(varOne);
 
std::cout << varTwo << "\n";
 
system("pause");
return 0;
}


Тут как я понимаю в строчке 3 D присваивается значение 5 и внутри функции я его не могу менять, т.е. на строчке 5 мне выдаст ошибку.


Цитата Сообщение от Jupiter Посмотреть сообщение
такая запись допустима только для методов класса.
означает она то что этот метод класса не модифицирует состояние объекта.
внутри такого метода нельзя модифицировать поля класса
А с вот этим бы хотелось уточнить т.е. если у меня есть переменная-член var и функция int fun (int var) const { } должна ее изменить, допустим прибавить 1 к ней, то эта функция не будет работать, компилятор выдаст ошибку?

Добавлено через 11 минут
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream> 
 
class mat
{
public:
mat(): var(0) {}
mat(int rhs): var(rhs) {}
~mat() {}
 
void set_var(int rhs) {var = rhs;}
int get_var() {return var;}
 
int plus_odin() const { var++; return var; }
 
private:
int var;
};


Вот дописал программу - класс, как я понимаю строка 13 ошибочная из-за const.
Yandex
Объявления
19.06.2013, 14:20     Передача в функцию - ссылки, указатели, константы
Ответ Создать тему
Опции темы

Текущее время: 21:35. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru