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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 213, средняя оценка - 4.71
thedriveee
3 / 3 / 1
Регистрация: 16.09.2012
Сообщений: 107
18.09.2012, 21:57     Передача данных по значению и по ссылке #1
Всем привет!

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

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

Заранее спс за хелп!
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.09.2012, 21:57     Передача данных по значению и по ссылке
Посмотрите здесь:

C++ Сравнение утраивания переменной по значению и по ссылке
Указатели, адресная арифметика и передача аргументов функций по значению и по ссылке C++
Помогите разобраться(С)Cпособы передачи аргументов в вызываемые функции: по значению, указателю и ссылке C++
C++ 3мя способами, по значению, по ссылке, через указатель
Передача параметров функции по значению, ссылке и указателю C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
John Prick
754 / 687 / 123
Регистрация: 27.07.2012
Сообщений: 1,974
Завершенные тесты: 3
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), так как в функцию передавался сам объект (переменная) х и её значение в функции изменилось.
thedriveee
3 / 3 / 1
Регистрация: 16.09.2012
Сообщений: 107
18.09.2012, 22:25  [ТС]     Передача данных по значению и по ссылке #3
С этим то понятно...
А что если мы напишем (int *parametr)?
PSIAlt
 Аватар для PSIAlt
86 / 86 / 8
Регистрация: 19.06.2012
Сообщений: 245
18.09.2012, 22:35     Передача данных по значению и по ссылке #4
Цитата Сообщение от thedriveee Посмотреть сообщение
С этим то понятно...
А что если мы напишем (int *parametr)?
Вызывающей функции придется делать операцию взятия адреса для каждой переменной: &x
А вообще, по ссылке я считаю предпочтительнее. Оно скрывает реализацию (что на самом деле там генерится код с указателем), да и вызывающей стороне обычно(не всегда) меньше мороки, да и это какбы более c++ - way
John Prick
754 / 687 / 123
Регистрация: 27.07.2012
Сообщений: 1,974
Завершенные тесты: 3
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
}
Немного сумбурно написал, но указатели не такая простая тема, чтоб в двух словах объяснить.
clickera
Сообщений: n/a
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
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 325
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 Хотя я не понимаю, как работает второй вариант. В первом всё понятно, передётся указатель, и изменяется значение по адресу, который хранится в указателе. Ну а как понять второй вариант? Там просто передаётся переменаая, а в функции уже мелькает её адрес... Не понимаю, как это работает. Получается, можно вобще без указателей обходиться, таким образом.
uglyPinokkio
325 / 228 / 41
Регистрация: 30.05.2014
Сообщений: 682
04.06.2014, 12:22     Передача данных по значению и по ссылке #8
Цитата Сообщение от Pro100Tom Посмотреть сообщение
но с другой стороны тот факт, что юзер может не знать, что функция изменяет значение (ведь, как я понял, не видно, что передается по значение)
Видно, что передается ссылка. Если она не константная, параметр может быть изменен.
randy92
7 / 7 / 2
Регистрация: 23.04.2014
Сообщений: 59
04.06.2014, 12:23     Передача данных по значению и по ссылке #9
вот тут все понятно объяснено
http://www.learncpp.com/cpp-tutorial...-by-reference/
http://www.learncpp.com/cpp-tutorial...ts-by-address/
Pro100Tom
 Аватар для Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 325
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. Спасибо, кстати.
uglyPinokkio
325 / 228 / 41
Регистрация: 30.05.2014
Сообщений: 682
04.06.2014, 12:43     Передача данных по значению и по ссылке #11
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Я это имел ввиду:
Тут имеется в виду, что вызов функции, принимающей параметр по ссылке, в коде выглядит так же, как вызов функции, принимающей параметр по значению. ИМХО - натянуто. Если это функция твоя, то ты должен знать свой код. Если чужая - должен знать ее интерфейс.
Gourmand
0 / 0 / 0
Регистрация: 29.01.2015
Сообщений: 30
29.01.2015, 13:44     Передача данных по значению и по ссылке #12
Код генерируется одинаковый, эта примочка с передачей по ссылке была сделана для трех целей - 1) упрощение изучения слабыми программистами, которым сложно пользоваться указателями 2) унификация с языками, где нет указателей, и нельзя написать a->b->c->d 3) упрощения переноса части кода, содержащего обращение к методам объектов в функцию - в ней не потребуется заменять точки на ->

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

Проблема указателей в том, что они могут быть 1) нулевые 2) неинициализированные. Этих двух причин более чем достаточно чтобы отказаться от их использования в пользу ссылок во всех случаях, где это возможно.
hoggy
5226 / 2117 / 403
Регистрация: 15.11.2014
Сообщений: 4,801
Завершенные тесты: 1
29.01.2015, 15:52     Передача данных по значению и по ссылке #14
Цитата Сообщение от Gourmand Посмотреть сообщение
Код генерируется одинаковый
Не факт. В общем случае ссылка лучше оптимизируется.

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

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

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

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

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

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

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

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

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

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

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

И не требует дополнительных проверок на нуль.
Но при этом имеет меньше "мощности", чем указатель.
То есть, именно 1-й вариант - это для тех, кто имеет ниже квалификацию, не умеет грамотно работать с указателями.
hoggy
5226 / 2117 / 403
Регистрация: 15.11.2014
Сообщений: 4,801
Завершенные тесты: 1
29.01.2015, 20:08     Передача данных по значению и по ссылке #16
Цитата Сообщение от Gourmand Посмотреть сообщение
Не верю, что ссылка лучше оптимизируется. Адресация на уровне команд процессора соответствует как раз случаю, когда именно указатель в регистре находится, и при необходимости индексируется содержимым другого регистра или ячейки памяти.
Мне на самом деле не очень интересно во что вы верите.
Передача в функцию по ссылке или указателю

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

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

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

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

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

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

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

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

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

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

Вот это уже признак низкой квалификации.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11828 / 6807 / 769
Регистрация: 27.09.2012
Сообщений: 16,878
Записей в блоге: 2
Завершенные тесты: 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

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

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

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

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

Добавлено через 4 минуты
Цитата Сообщение от Voivoid Посмотреть сообщение
Грамотно работать с указателями". Для любого человека в теме это звучит примерно как: грамотно работать с таблицей умножения. Весь мир старается любой ценой бороться со сложностью разработки.
Бороться с указателями - всё равно, что бороться с таблицей умножения. И работать с указателями также несложно, как с таблицей умножения. Но этого почему-то большинство программистов страшно боится. Хотя это более мощный механизм, чем ссылки. В результате с использованием только ссылок код получается более громоздкий и сложный. То есть, эффект ровно обратный.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.01.2015, 14:40     Передача данных по значению и по ссылке
Еще ссылки по теме:

C++ Массив и классы (как передаётся объект: по значению или по ссылке?)
Передача параметров в функцию по значению, по ссылке или по указателю C++
Передача параметров в функцию по значению, по ссылке и по указателю C++

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

Или воспользуйтесь поиском по форуму:
hoggy
5226 / 2117 / 403
Регистрация: 15.11.2014
Сообщений: 4,801
Завершенные тесты: 1
30.01.2015, 14:40     Передача данных по значению и по ссылке #20
Цитата Сообщение от Voivoid Посмотреть сообщение
Какой уж там boost::function
Ну хз, может быть.

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

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

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

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

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

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

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

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

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

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

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

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

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


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


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

Использование указателя там, где по смыслу нужна ссылка - это выдает либо новичка,
который ни бум бум,
либо сишника, чьи мозги настолько закостенели,
что уже просто не в состоянии перестроится на с++ лад.
Yandex
Объявления
30.01.2015, 14:40     Передача данных по значению и по ссылке
Ответ Создать тему
Опции темы

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