Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.93/30: Рейтинг темы: голосов - 30, средняя оценка - 4.93
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
1

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

16.06.2013, 23:18. Показов 5925. Ответов 37
Метки нет (Все метки)

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

Кликните здесь для просмотра всего текста
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 и чем отличается такая же программа без &.

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

Это первый вопрос в этой теме, дальше я буду добавлять вопросы, про указатели константы и т.д. так что если что, смотрите последние сообщения, а не первое.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.06.2013, 23:18
Ответы с готовыми решениями:

Передача в функцию константы вместо указателя
Копаясь в чужом коде, обнаружил для себя странность в вызове функции. В C++ я разбираюсь слабо. ...

Ссылки и указатели на функцию
Если передавать значение в функцию через указатель и ссылку,то в обоих случаях передаётся адрес,а...

Передача в функцию через указатели
Компилятор говорит, что что-то не так с передачей max и min. Что? #include &lt;stdio.h&gt; #include...

Передача массива в функцию (указатели)
Возникла проблема. Написала программу решение систем линейных уравнений методом Гаусса. В студии 12...

37
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
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); //ошибка, функция возвращает ссылку на временный объект
В общем случае возвращать ссылку - плохая примета.
0
интересующийся
311 / 282 / 93
Регистрация: 25.09.2010
Сообщений: 1,056
16.06.2013, 23:32 3
Всё зависит от конкретного компилятора. В стандарте написано, что возврат ссылки на локальный объект приводит к UB.
0
419 / 418 / 72
Регистрация: 27.05.2012
Сообщений: 1,168
16.06.2013, 23:34 4
Цитата Сообщение от VLK Посмотреть сообщение
& в строке 3
означает что функция возвращает ссылку на переменную

Цитата Сообщение от VLK Посмотреть сообщение
чем отличается такая же программа без &.
если бы не было & то функция производила манипуляции с переменной, делала её копию и возвращала к месту вызова
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
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 происходит неопределенное поведение, так как ссылка ссылается на не существующую переменную.
что происходит дальше - на совести разработчиков компилятор, возможно все!
вот и сказочке конец...
2
419 / 418 / 72
Регистрация: 27.05.2012
Сообщений: 1,168
16.06.2013, 23:38 6
Цитата Сообщение от Olivеr Посмотреть сообщение
int &vatTwo = fun(vatOne); //ошибка, функция возвращает ссылку на временный объект

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

извините за колхозное описание ситуации, мне так проще понять.
0
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
16.06.2013, 23:43 8
VLK, если записано
C++
1
int & fun(int rhs)
и
C++
1
varTwo = fun(varOne);
то происходит копирование rhs в переменную varTwo

По крайней мере так в
Цитата Сообщение от Кудаив Посмотреть сообщение
MinGW
0
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
16.06.2013, 23:44  [ТС] 9
Цитата Сообщение от Olivеr Посмотреть сообщение
VLK, если записано
C++
1
int & fun(int rhs)
и
C++
1
varTwo = fun(varOne);
то происходит копирование rhs в переменную varTwo

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

Добавлено через 1 минуту
Совет: напишите простенькую структуру со всеми конструкторами и деструктором. В их телах выведите на экран сообщение о том, что вызван такой то конструктор/деструктор. И проделайте ту же программу с этой структурой.
0
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
17.06.2013, 00:02  [ТС] 11
Все равно не вижу, не понимаю разницу между
C++
1
int & fun(int rhs)
и
C++
1
int fun(int rhs)
Ладно, завтра продолжу изучение.
0
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
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;
}
0
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
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) работают по разному.
0
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
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; //возвращается ссылка на временный объект. после выхода из функции временный объект уничтожится и ссылка будет указывать на непонятно что
}
0
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
17.06.2013, 19:08  [ТС] 15
Это я понимаю, получается что такая запись изначально ошибочная и не должна использоваться вообще, НО - https://www.cyberforum.ru/post955770.html

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

PS кстати данную программу я хотел повторить, половина работает, но не работает строчка1 = строчк2 + строчка3 и я думаю проблема как раз кроется в этих строчках 17 и 21, но я их не понимаю по этому не могу толком найти проблему.
0
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
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, но я их не понимаю по этому не могу толком найти проблему.
В вашей программе не перегружен оператор +
0
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
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) { }
0
415 / 411 / 95
Регистрация: 06.10.2011
Сообщений: 832
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
1
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
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, но если такое потребовалось то вы явноно что-то делаете не так.
1
198 / 170 / 19
Регистрация: 05.05.2013
Сообщений: 1,235
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.
0
19.06.2013, 14:20
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.06.2013, 14:20
Помогаю со студенческими работами здесь

Как лучше передавать значения в функцию? Ссылки vs указатели
Всем доброго времени суток. Уважаемые гуру, подскажите пожалуйста, как лучше передавать значения в...

Передача параметров в функцию через указатели
Описать внешнюю функцию которая получает целое значение и возвращает число с обращенным порядком...

Передача значений в функцию через указатели
Ребят, подскажите как правильно расставить указатели, чтобы при вызове функции правильно...

Указатели Char, передача адреса в функцию
в данном случае проблема выглядит следующим образом: main(void) { char *map, *moves; ...


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

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