4 / 4 / 1
Регистрация: 16.09.2012
Сообщений: 119
1

Передача данных по значению и по ссылке

18.09.2012, 21:57. Показов 54391. Ответов 32
Метки нет (Все метки)

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

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

*var и &var в чем между ними разница, когда мы их передаем в качестве параметров функции?

Заранее спс за хелп!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.09.2012, 21:57
Ответы с готовыми решениями:

Передача по ссылке и по значению
Эта тема стара как мир, но я хотел уточнить одну вещь. QBluetoothAddress* address = new...

С - > C# Передача значений по ссылке и значению
Есть Си функция: double lagrange(double X, double *Xi, double *Yi, int n) //Аппроксимация...

Передача в метод по ссылке и по значению
Запутался малость... class Program { static void Main(string args) ...

Передача параметров по указателю, ссылке и значению
Задание: Вычислить Y(x) и S(x). (где x принадлежит диапазону ) Y(x) и S(x) реализовать в виде...

32
2268 / 1761 / 739
Регистрация: 27.07.2012
Сообщений: 5,233
18.09.2012, 22:24 2
Ссылка - это по сути второе имя того же самого объекта. Когда в функцию передаётся объект по ссылке, то передаётся фактически этот объект. Когда же мы передаём объект по значению, то в функцию передаётся его копия.
Допустим, есть такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void func_1(int a) // передача по значению
{
   a = a + 100500;
}
 
void func_2(int & a) // передача по ссылке
{
    a = a + 100500;
}
 
int main()
{
   int x = 12345;
   func_1(x);
   cout << x;
   func_2(x);
   cout << x;
}
В первом случае выведется значние x, равное начальному - 12345, так как в первую функцию передавалась не сама переменнаяx, а её значени. Во втором случае выведется значение 112845 (100500 + 12345), так как в функцию передавался сам объект (переменная) х и её значение в функции изменилось.
3
4 / 4 / 1
Регистрация: 16.09.2012
Сообщений: 119
18.09.2012, 22:25  [ТС] 3
С этим то понятно...
А что если мы напишем (int *parametr)?
0
87 / 87 / 1
Регистрация: 19.06.2012
Сообщений: 245
18.09.2012, 22:35 4
Цитата Сообщение от thedriveee Посмотреть сообщение
С этим то понятно...
А что если мы напишем (int *parametr)?
Вызывающей функции придется делать операцию взятия адреса для каждой переменной: &x
А вообще, по ссылке я считаю предпочтительнее. Оно скрывает реализацию (что на самом деле там генерится код с указателем), да и вызывающей стороне обычно(не всегда) меньше мороки, да и это какбы более c++ - way
1
2268 / 1761 / 739
Регистрация: 27.07.2012
Сообщений: 5,233
18.09.2012, 22:37 5
Цитата Сообщение от thedriveee Посмотреть сообщение
А что если мы напишем (int *parametr)?
Это уже передача указателя. По большому счёту, отношения к т.н. дуализму передачи по ссылке/значению не имеет. Указатель - это адрес объекта в памяти. Когда в С++ не сущестовало ссылок, так передавали в функции объекты, которые нужно было изменить внутри функции или чтобы избежать копирования объекта (которое происходит при передаче по значению), но все эти вещи сейчас решают ссылки проще и безопаснее.

Работают указатели примерно так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
void func_3(int * a) //передаём указатель
{
   *a = *a + 100500; // указатель необходимо разыменовывать,
   // чтобы получить доступ к значению переменной
}
 
int main()
{
   int x = 12345;
   func_3(&x); // мы передаём в функцию не x, а адрес x (применяем оператор взятия адреса - &)
   // тут значение x = 112845
}
Немного сумбурно написал, но указатели не такая простая тема, чтоб в двух словах объяснить.
3
clickera
25.04.2013, 02:24 6
Здраствуйте. Аналогична ситуация. С указателями никак не могу разобратся
Есть класс, в котором есть функция которая сравнивает две строки char.
Функция
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool char_equal( char* str1, char* str2 ){
        int i = 0;
        int len_str1 = strlen(str1);
        int len_str2 = strlen(str2);
        while( true ){
            if( str1[i] == '\0' || str2[i] == '\0' ) break;
            if( str1[i] == str2[i] ){
                i++;
            }else{
                break;
//                 return false;
            }
        };
        // cout << i << " " << len_str1 << " " << len_str2 << " " << str1 << " " << str2 << " " << "\n"; // отладка
        if( i == len_str1 && len_str2 == i ) return true;
        return false;
    }
Код вызова функции
C++
1
2
3
4
5
6
char buf[8][20] = {"-r", "--recursive", "-f", "--remove-files", "-d", "--remove-dirs", "-e", "-F"};
....
char cCInName;
.....
cCInName = *"-F";
cout << char_equal(&cCInName, buf[7]) << "\n";
Так вот при вызове &cCInName передается что то непонятное, тогда как buf[7] передается нормально. Почему так?
Вот вывод отладки из консоли (красным отметил перевый значение первого аргумента):

1 6 2 --0� -F
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
04.06.2014, 12:17 7
А какой способ более оптимальный в плане использования памяти и скорости?
C++
1
2
void someFunction(int* number){*number*=2;}
int main(){int myNumber=5; someFunction(&myNumber)}
или такой:
C++
1
2
void someFunction(int &number){number*=2;}
int main() {int myNumber=5; someFunction(myNumber)}
Мне больше нравится второй вариант, так как один раз знак & написал и больше заморачиваться не надо, но с другой стороны тот факт, что юзер может не знать, что функция изменяет значение (ведь, как я понял, не видно, что передается по значение) может вызвать некое недопонимание что-ли. Поправьте, если не прав.
P.S Хотя я не понимаю, как работает второй вариант. В первом всё понятно, передётся указатель, и изменяется значение по адресу, который хранится в указателе. Ну а как понять второй вариант? Там просто передаётся переменаая, а в функции уже мелькает её адрес... Не понимаю, как это работает. Получается, можно вобще без указателей обходиться, таким образом.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
04.06.2014, 12:22 8
Цитата Сообщение от Pro100Tom Посмотреть сообщение
но с другой стороны тот факт, что юзер может не знать, что функция изменяет значение (ведь, как я понял, не видно, что передается по значение)
Видно, что передается ссылка. Если она не константная, параметр может быть изменен.
0
8 / 8 / 4
Регистрация: 23.04.2014
Сообщений: 59
04.06.2014, 12:23 9
вот тут все понятно объяснено
http://www.learncpp.com/cpp-tu... reference/
http://www.learncpp.com/cpp-tu... y-address/
1
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
04.06.2014, 12:30 10
Цитата Сообщение от Pro100Tom Посмотреть сообщение
...что передается по значение
Сорри, не проснулся еще. Имел ввиду, не видно, что передаётся сама переменная, а не её копия.

Добавлено через 5 минут
Цитата Сообщение от uglyPinokkio Посмотреть сообщение
Видно, что передается ссылка. Если она не константная, параметр может быть изменен.
Я это имел ввиду:
It’s impossible to tell from the function call that the argument may change. An argument passed by value and passed by reference looks the same. We can only tell whether an argument is passed by value or reference by looking at the function declaration. This can lead to situations where the programmer does not realize a function will change the value of the argument.
Из ссылки от Randy92. Спасибо, кстати.
0
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
04.06.2014, 12:43 11
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Я это имел ввиду:
Тут имеется в виду, что вызов функции, принимающей параметр по ссылке, в коде выглядит так же, как вызов функции, принимающей параметр по значению. ИМХО - натянуто. Если это функция твоя, то ты должен знать свой код. Если чужая - должен знать ее интерфейс.
0
1 / 1 / 1
Регистрация: 29.01.2015
Сообщений: 72
29.01.2015, 13:44 12
Код генерируется одинаковый, эта примочка с передачей по ссылке была сделана для трех целей - 1) упрощение изучения слабыми программистами, которым сложно пользоваться указателями 2) унификация с языками, где нет указателей, и нельзя написать a->b->c->d 3) упрощения переноса части кода, содержащего обращение к методам объектов в функцию - в ней не потребуется заменять точки на ->

А чем пользоваться - дело программиста. Кто перешел с языка С, те пользуются указателями. Кто перешел с Паскаля или Васика, те пользуются передачей по ссылке.
0
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
29.01.2015, 14:28 13
Цитата Сообщение от Gourmand Посмотреть сообщение
1) упрощение изучения слабыми программистами, которым сложно пользоваться указателями 2) унификация с языками, где нет указателей, и нельзя написать a->b->c->d 3) упрощения переноса части кода, содержащего обращение к методам объектов в функцию - в ней не потребуется заменять точки на ->
Лол, кажется это одно из самых бредовых высказываний из тех, что я слышал на эту тему.

Проблема указателей в том, что они могут быть 1) нулевые 2) неинициализированные. Этих двух причин более чем достаточно чтобы отказаться от их использования в пользу ссылок во всех случаях, где это возможно.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.01.2015, 15:52 14
Цитата Сообщение от Gourmand Посмотреть сообщение
Код генерируется одинаковый
Не факт. В общем случае ссылка лучше оптимизируется.

Цитата Сообщение от Gourmand Посмотреть сообщение
А чем пользоваться
Зависит от задачи.

C++
1
void foo(some*); //<--- допускает nullptr.
Используется либо для низкоуровневой работы с памятью.

Либо когда необходимо предоставить возможность передать аргументы,
которые просигнализируют: "если меня нет, используете дефолтное".

Такое сплошь и рядом используется в сишном апи:
функция может принимать кучу аргументов.
Но заполнить достаточно только важные для пользователя.
Вместо нулей будут использованы значения по умолчанию.

C++
1
void bar(some&); //<--- работает только с "реальным" объектом
Ссылка удобна тем, что улучшает читабельность кода,
лучше передавая намерения автора кода.

И не требует дополнительных проверок на нуль.
0
1 / 1 / 1
Регистрация: 29.01.2015
Сообщений: 72
29.01.2015, 19:10 15
Цитата Сообщение от Voivoid Посмотреть сообщение
Проблема указателей в том, что они могут быть 1) нулевые 2) неинициализированные.
Вот это как раз 1-й случай - нулевые и неиницализированные указатели представляют проблему для программистов, которые не умеют работать с указателями.

Добавлено через 14 минут
Цитата Сообщение от hoggy Посмотреть сообщение
Не факт. В общем случае ссылка лучше оптимизируется.
Не верю, что ссылка лучше оптимизируется. Адресация на уровне команд процессора соответствует как раз случаю, когда именно указатель в регистре находится, и при необходимости индексируется содержимым другого регистра или ячейки памяти.

Цитата Сообщение от hoggy Посмотреть сообщение
C++
1
void foo(some*); //<--- допускает nullptr.
Используется либо для низкоуровневой работы с памятью.

Либо когда необходимо предоставить возможность передать аргументы,
которые просигнализируют: "если меня нет, используете дефолтное".
Еще чаще в случае "объект не существует, работать с ним нельзя". Такое распространено при использовании плагинов.

И еще когда объекты представляют собой иерархию, но не классов, а экземпляров. В таком случае в методы объектов приходится передавать указатели, поскольку в иерархии хранятся они, а не ссылки. Наилучший пример - мощный и развитый мультиплатформенный фреймворк Qt. В нем передача параметров по ссылке почти не используется, а по указателям сплошь и рядом.

Цитата Сообщение от hoggy Посмотреть сообщение
Ссылка удобна тем, что улучшает читабельность кода,
лучше передавая намерения автора кода.

И не требует дополнительных проверок на нуль.
Но при этом имеет меньше "мощности", чем указатель.
То есть, именно 1-й вариант - это для тех, кто имеет ниже квалификацию, не умеет грамотно работать с указателями.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.01.2015, 20:08 16
Цитата Сообщение от Gourmand Посмотреть сообщение
Не верю, что ссылка лучше оптимизируется. Адресация на уровне команд процессора соответствует как раз случаю, когда именно указатель в регистре находится, и при необходимости индексируется содержимым другого регистра или ячейки памяти.
Мне на самом деле не очень интересно во что вы верите.
https://www.cyberforum.ru/post5873145.html

Цитата Сообщение от Gourmand Посмотреть сообщение
Еще чаще в случае "объект не существует, работать с ним нельзя". Такое распространено при использовании плагинов.
Ну это уже из области низкой квалификации.
Если без живого объекта работать нельзя, значит указатель не нужен.
Тут по смыслу нужна именно ссылка, и на нуль проверять не придется.

Нафига принимать указатель, что бы потом обязательно проверять его на nullptr,
а пользователя напрягать: вот прототип принимает указатель,
но сюда обязательно нужно живой объект, а не просто адрес.

Цитата Сообщение от Gourmand Посмотреть сообщение
Наилучший пример - мощный и развитый мультиплатформенный фреймворк Qt. В нем передача параметров по ссылке почти не используется, а по указателям сплошь и рядом.
В нем ничего не мешает использовать ссылки.

Что до идеологии - не видитесь на авторитеты.
Они и шаблоны изначально не осилили.
Им показалось проще запилить собственный костыль-препроцессор, нежели осилить boost::function и аналоги для создания технологии слотов/сигналов.

Вот и получилось, что кютешные слоты/сигналы - тормозной рантайм.
На вскидку они в тысячи раз медленнее работают, чем тот же std::function

Хорошая новость в том, что использовать std::function там так же ничего не мешает.

Цитата Сообщение от Gourmand Посмотреть сообщение
Но при этом имеет меньше "мощности", чем указатель.
"Мощность" ради "мощности" не нужна.

Цитата Сообщение от Gourmand Посмотреть сообщение
То есть, именно 1-й вариант - это для тех, кто имеет ниже квалификацию, не умеет грамотно работать с указателями.
По поводу квалификации:
-- там где по смыслу требуется работать именно с указателем, работают с указателем.

-- там где по смыслу требуется работать с живым объектом ,
работают с ссылкой, или с объектом по значению (зависит от ситуации)

Использования вещи не по назначению:
Нужен живой объект. Но мы же не ищем легких путей.
Сначала мы сделаем кривой сбивающий с толку прототип,
а потом начнем вставлять проверки: а живой ли нам прислали?

Вот это уже признак низкой квалификации.
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
29.01.2015, 20:15 17
Первый пост: 18.09.2012
Спустя более полугода подняли тему: 25.04.2013
Прошло больше года и снова подняли: 04.06.2014
И теперь еще раз: 28.01.15

Дайте уже умереть этой теме спокойно, некроманты

Добавлено через 20 секунд
Первый пост: 18.09.2012
Спустя более полугода подняли тему: 25.04.2013
Прошло больше года и снова подняли: 04.06.2014
И теперь еще раз: 28.01.15

Дайте уже умереть этой теме спокойно, некроманты
0
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
29.01.2015, 23:33 18
Цитата Сообщение от hoggy Посмотреть сообщение
Они и шаблоны изначально не осилили. Им показалось проще запилить собственный костыль-препроцессор, нежели осилить boost::function и аналоги для создания технологии слотов/сигналов.
Ну справедливости ради надо сказать, что QT начинали писать чуть-ли не в начале 90-х. В те времена плюсы были мягко говоря, кхм, не в лучшей своей форме. Поэтому ничего удивительного, все фреймворки и библиотеки того времени велосипедили со страшной силой ( тот же MFC например ). Какой уж там boost::function

Цитата Сообщение от Gourmand Посмотреть сообщение
То есть, именно 1-й вариант - это для тех, кто имеет ниже квалификацию, не умеет грамотно работать с указателями.
Пололлировал. Детектирую в тебе C'шника. Грамотно работать с указателями". Для любого человека в теме это звучит примерно как: грамотно работать с таблицей умножения. Но только C'шники говорят об этом с придыханием, как о нечто удивительном.

Весь мир старается любой ценой бороться со сложностью разработки, но мы-то, благодаря Gourmand'у, теперь знаем, что это все ерунда. Решение оказывается простое - надо-то всего лишь никогда не делать ошибок, лол.
0
1 / 1 / 1
Регистрация: 29.01.2015
Сообщений: 72
30.01.2015, 14:06 19
Цитата Сообщение от hoggy Посмотреть сообщение
Им показалось проще запилить собственный костыль-препроцессор, нежели осилить boost::function и аналоги для создания технологии слотов/сигналов.

Вот и получилось, что кютешные слоты/сигналы - тормозной рантайм.
На вскидку они в тысячи раз медленнее работают, чем тот же std::function
Типичная демонстрация непонимания, зачем и почему сигнал-слоты именно так сделаны, как сделаны. На самом деле,
C++
1
Qt::DirectConnection
работает со скоростью прямых вызовов. А остальные реализованы через очередь, также и с возможностью блокировки. Причем очередь автоматически работает для любых зарегистрированных типов данных. Что позволяет с помощью QThread легко делать асинхронную параллельную обработку данных без использования семафоров или мутексов (хотя они тоже в Qt есть). И фреймворк Qt потом это всё сам раскидывает по процессорным ядрам. Где тут рядом лежит boost, не видно совершенно.

Добавлено через 4 минуты
Цитата Сообщение от Voivoid Посмотреть сообщение
Грамотно работать с указателями". Для любого человека в теме это звучит примерно как: грамотно работать с таблицей умножения. Весь мир старается любой ценой бороться со сложностью разработки.
Бороться с указателями - всё равно, что бороться с таблицей умножения. И работать с указателями также несложно, как с таблицей умножения. Но этого почему-то большинство программистов страшно боится. Хотя это более мощный механизм, чем ссылки. В результате с использованием только ссылок код получается более громоздкий и сложный. То есть, эффект ровно обратный.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
30.01.2015, 14:40 20
Цитата Сообщение от Voivoid Посмотреть сообщение
Какой уж там boost::function
Ну хз, может быть.

Цитата Сообщение от Gourmand Посмотреть сообщение
На самом деле, Qt:irectConnection работает со скоростью прямых вызовов. А остальные реализованы через очередь, такж и с возможностью блокировки. Причем очередь автоматически работает для любых зарегистрированных типов данных. Что позволяет легко делать асинхронную параллельную обработку данных без использования семафоров или мутексов (хотя они тоже в Qt есть). И фреймворк потом это сам раскидывает по процессорным ядрам.
Очевидно, что все тоже самое можно было бы сделать и без необходимости велосипедить собственный препроцессор.

Но мне бы не хотелось сейчас скатываться в тему кути.
Кутя - замичательный фреймворк.
И его киллер-фича - это тщательно продуманный дизайн.
Имхо: один из лучших в своем роде.

Цитата Сообщение от Gourmand Посмотреть сообщение
И работать с указателями также несложно, как с таблицей умножения. Но этого почему-то большинство программистов страшно боится. Хотя это более мощный механизм, чем ссылки.
Меня забавляют люди, которые используют слово "боится".
Право же - детский сад.

Классика жанра:

- я использую RAII, смарты. И мне больше не приходится вручную за всем следить

- да ты просто не осилил сырых указателей, и боишься вручную использовать new !!!!!
А по поводу мощностей:

- мы хотим ездить по городу и цеплять молоденьких цыпочек. Нам нужен легковое спортивное авто.
- давай купим танк.
- ????
- но ведь он более мощный...
Ответьте мне на один простой вопрос: зачем?

Зачем вам нужны "мощности указателя", если все что вам нужно в этой конкретной задаче,
для этой конкретной функции - это работать с нормальным, живым объектом?
----------------------------------

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

Но эти свойства позволяют на с++ проворачивать такие штуки,
которые сишникам и не снились.

Цитата Сообщение от Gourmand Посмотреть сообщение
В результате код получается более громоздкий и сложный.
Неужели?

Вообще то как раз таки наоборот.

Обращение с ссылкой столь же простое, как и с обычным объектом.
Её и нужно воспринимать, как псевдоним оригинального объекта.
И код получается таким же простым, как будто бы вы работаете с обычным объектом.


В отличи от указателя, который как минимум нужно проверять на нулль,
думать о том, нужно ли выделять/чистить память для него, и тд и тп.


------------------------------------------------------------------

Использование указателя там, где по смыслу нужна ссылка - это выдает либо новичка,
который ни бум бум,
либо сишника, чьи мозги настолько закостенели,
что уже просто не в состоянии перестроится на с++ лад.
1
30.01.2015, 14:40
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.01.2015, 14:40
Помогаю со студенческими работами здесь

Передача объекта по ссылке или о значению
Да, да, снова этот вопрос. Допустим у меня есть объект Student с полями String surname и String...

Конструкторы копирования, передача по ссылке и значению
Здравствуйте! Вопрос: существует конструктор копирования, которые принимает константный обьект по...

Передача параметров функции по значению, ссылке и указателю
Вычислить F=f(a)-5f^3(sin(b/2))+1/f(1+c^4), де f(x)=3x^2-2x^2+7, при a=5.08, b=-0.65, c=3.87 ...

Передача std::string по константной ссылке \ значению
Суть вопроса: есть простенький словарь с std::vector в качестве приватного поля. struct...


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

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

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