Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

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

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

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

Всем привет!

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

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

Заранее спс за хелп!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.09.2012, 21:57
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Передача данных по значению и по ссылке (C++):

Передача по ссылке и по значению - C++
Эта тема стара как мир, но я хотел уточнить одну вещь. QBluetoothAddress* address = new QBluetoothAddress("00:1A:7D:DA:71:15"); ...

Передача std::string по константной ссылке \ значению - C++
Суть вопроса: есть простенький словарь с std::vector в качестве приватного поля. struct StudentGrade { std::string name; char...

Передача параметров в функцию по значению, по ссылке и по указателю - C++
Доброе время суток товарищи программисты. Столкнулся с кучей ошибок в написании простой программы. Задача заключается в том чтобы написать:...

Передача параметров функции по значению, ссылке и указателю - C++
Вычислить 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 Добавлено через 45 минут #include...

Передача параметров в функцию по значению, по ссылке или по указателю - C++
Передача параметров в функцию по значению, по ссылке или по указателю. Чем отличаются эти 3 способа. И, если не сложно, привести...

Указатели, адресная арифметика и передача аргументов функций по значению и по ссылке - C++
Подскажите, пожалуйста, как решить такую задачу вручную. На экзамене предложат задание такого типа НА БУМАГЕ, и надо будет написать, что...

32
John Prick
824 / 757 / 152
Регистрация: 27.07.2012
Сообщений: 2,156
Завершенные тесты: 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), так как в функцию передавался сам объект (переменная) х и её значение в функции изменилось.
3
thedriveee
3 / 3 / 1
Регистрация: 16.09.2012
Сообщений: 107
18.09.2012, 22:25  [ТС] #3
С этим то понятно...
А что если мы напишем (int *parametr)?
0
PSIAlt
87 / 87 / 8
Регистрация: 19.06.2012
Сообщений: 245
18.09.2012, 22:35 #4
Цитата Сообщение от thedriveee Посмотреть сообщение
С этим то понятно...
А что если мы напишем (int *parametr)?
Вызывающей функции придется делать операцию взятия адреса для каждой переменной: &x
А вообще, по ссылке я считаю предпочтительнее. Оно скрывает реализацию (что на самом деле там генерится код с указателем), да и вызывающей стороне обычно(не всегда) меньше мороки, да и это какбы более c++ - way
1
John Prick
824 / 757 / 152
Регистрация: 27.07.2012
Сообщений: 2,156
Завершенные тесты: 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
}
Немного сумбурно написал, но указатели не такая простая тема, чтоб в двух словах объяснить.
3
clickera
0 / 0 / 0
Регистрация: 21.04.2013
Сообщений: 1
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
0
Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 331
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
uglyPinokkio
326 / 229 / 41
Регистрация: 30.05.2014
Сообщений: 682
04.06.2014, 12:22 #8
Цитата Сообщение от Pro100Tom Посмотреть сообщение
но с другой стороны тот факт, что юзер может не знать, что функция изменяет значение (ведь, как я понял, не видно, что передается по значение)
Видно, что передается ссылка. Если она не константная, параметр может быть изменен.
0
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/74-passing-arguments-by-address/
1
Pro100Tom
69 / 28 / 7
Регистрация: 29.10.2012
Сообщений: 331
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
uglyPinokkio
326 / 229 / 41
Регистрация: 30.05.2014
Сообщений: 682
04.06.2014, 12:43 #11
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Я это имел ввиду:
Тут имеется в виду, что вызов функции, принимающей параметр по ссылке, в коде выглядит так же, как вызов функции, принимающей параметр по значению. ИМХО - натянуто. Если это функция твоя, то ты должен знать свой код. Если чужая - должен знать ее интерфейс.
0
Gourmand
1 / 1 / 1
Регистрация: 29.01.2015
Сообщений: 65
29.01.2015, 13:44 #12
Код генерируется одинаковый, эта примочка с передачей по ссылке была сделана для трех целей - 1) упрощение изучения слабыми программистами, которым сложно пользоваться указателями 2) унификация с языками, где нет указателей, и нельзя написать a->b->c->d 3) упрощения переноса части кода, содержащего обращение к методам объектов в функцию - в ней не потребуется заменять точки на ->

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

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

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

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

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

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

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

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

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

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

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

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

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

И не требует дополнительных проверок на нуль.
Но при этом имеет меньше "мощности", чем указатель.
То есть, именно 1-й вариант - это для тех, кто имеет ниже квалификацию, не умеет грамотно работать с указателями.
0
29.01.2015, 19:10
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.01.2015, 19:10
Привет! Вот еще темы с ответами:

Передача аргумента в функцию по значению, по ссылке, по указателю: в чём концептуальная разница? - C++
Доброго всем здравия, прошу прощения, что достал уже всех этой темой. #include &lt;iostream&gt; using namespace std; int my_attemp(int...

Сравнение утраивания переменной по значению и по ссылке - C++
У Дейтлов есть задача: Я написал такой код: #include&lt;iostream&gt; using namespace std; #include&lt;windows&gt;

3мя способами, по значению, по ссылке, через указатель - C++
Дана последовательность действующих чисел с помощью процедуры обеспечить преобразование последовательности следующим образом: в начале...

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


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.