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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 102, средняя оценка - 4.97
xKirillx
1 / 1 / 0
Регистрация: 01.03.2011
Сообщений: 11
#1

Ссылки и указатели - C++

01.03.2011, 12:10. Просмотров 13151. Ответов 54
Метки нет (Все метки)

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

Указатели и ссылки - C++
Экспериментируя с указателями пришел к вот таким выводам: int a; //переменная int *b; //указатель int &c = a //ссылка на <a> ...

Ссылки, указатели - C++
Доброго времени. Как, используя ссылки, указатели и, возможно, другие приемы сделать что-то вроде этого?: int a = 1; int b = 2; ...

Указатели и Ссылки - C++
извеняюсь,но никак не могу понять. int sum(int* inLeft, int* inRight) { if(inLeft == inRight) return *inLeft; ...

Указатели и ссылки - C++
Допустим, что есть функция, в которую мы кидаем массив по указателю и кол-ву элементов. void printArray(int *arr, int elements) ...

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

Указатели и ссылки [С++] - C++
Всем привет. я тут программу делаю. Цель: определить,принадлежит ли точка заданному промежутку(а точнее лежит внутри или снаружи фигуры)....

54
Evg
Эксперт CАвтор FAQ
18377 / 6424 / 441
Регистрация: 30.03.2009
Сообщений: 17,838
Записей в блоге: 28
19.06.2011, 23:07 #16
Цитата Сообщение от Evg Посмотреть сообщение
2. При наличии модификатора const перед ссылкой можно быть железно уверенным в том, что ни при каких обстоятельствах значение передаваемого аргумента не изменится. Если же мы работаем с указателем, то в результате ошибки программиста значение может измениться, что приводит к очень трудноуловимым ошибкам, которые с виду выглядят как ошибки компилятора, потому что компилятор доверился модификатору const. Реально это ошибка программиста

C
1
2
3
4
5
6
7
8
9
/* С виду функция выглядит так, что по указателю значения изменяться
 * не должны. Компилятор в точке вызова функции может заложиться на это свойство */
void (const int *p)
{
  /* Но средствами языка мы вполне можем обойти признак const и сделать
   * запись по указателю. */
  int *pp = (int*) p;
  *pp = 0;
}
Добрые люди подсказали, что я не прав. Над ссылками можно проводить преобразование типа

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
void func (const int &p)
{
    int &ppp=(int&) p;
    ppp=100;
}
 
int main (void)
{
    int p = 10;
    std::cout << p << std::endl;
    func (p);
    std::cout << p << std::endl;
    return 0;
}
напечатает

Код
10
100
2
silentnuke
Android Programmer
139 / 140 / 5
Регистрация: 08.12.2010
Сообщений: 421
19.06.2011, 23:34 #17
угу, в продолжении к этому ещё 1 забавный момент
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
void func (const int &p)
{
    int &ppp=(int&) p;
    ppp=100;
}
 
int main (void)
{
    const int p = 10;
    std::cout << p << std::endl;
    func (p);
    std::cout << p << std::endl;
    return 0;
}
выведет
10
10
хотя смотрел по дебагу в памяти записано 100. Интересно особенности оптимизации mvs, или везде так, просто нет сейчас возможности проверить.
0
Jupiter
Каратель
Эксперт С++
6561 / 3982 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
19.06.2011, 23:41 #18
silentnuke, msvs просто в 13-ю и 15-ю строку вставляет 10, поставте вывод внутри функции
0
kravam
быдлокодер
1703 / 890 / 45
Регистрация: 04.06.2008
Сообщений: 5,489
19.06.2011, 23:46 #19
Переменные ссылочного типа. Просьба разжевать и положить в рот.
0
taras atavin
3570 / 1754 / 91
Регистрация: 24.11.2009
Сообщений: 27,567
20.06.2011, 06:20 #20
Цитата Сообщение от xKirillx Посмотреть сообщение
Добрый день. Возможно было. В чем существенная разница между передачей данных в функцию по ссылке или указателю. В каких случаях вы бы что рекоммендовали. Заранее спасибо.
Разница в том, что адрес ссылки нельзя поменять.
C++
1
2
3
char a="dfsasdf";
const char *p="dfsasdf"; // Константой является не только значение указателя, но это ещё и указатель на константу
char &b=a;// А здесь константа - только адрес, но само данное - переменная
. Имеешь ты адрес элемент линейного списка, надо перебрать список, с указателем это можно сделать, а со ссылкой нет:
C++
1
2
3
4
5
6
7
8
for (; list->next!=null; list->next) // Если list - указатель, то такой цикл допустим
{
 ...
}
for (; list.next!=null; list.next) // Даже если list - ссылка, то такой цикл всё равно не допустим
{
 ...
}
, поэтому при передаче сслыки, её придётся привести к указаетелю. Для массивов тоже существует арифметика указателей, но нет арифметики ссылок. Но в том случае, если один и тот же правметр используется для передачи адреса и в функцию, и из неё, различие не актуально: всё равно придётся использовать указатель на указатель, а его уже можно заменить ссылкой на указатель. Ссылка также применима и в том случае, если требуется вернуть не адрес, а значение по готовому адресу. Синтаксически же ссылка удобнее указателя.
C++
1
2
int a;
void f(int *a);
для вызова придётся использовать
C++
1
f(&a);
.
C++
1
2
int a;
void f(int &a);
, а здесь достаточно
C++
1
f(a);
.

Добавлено через 4 минуты
Цитата Сообщение от bigredcat Посмотреть сообщение
Вобще не встречал в описании языка C++ упоминания, что ссылка это указатель
А что на самом деле хранится в ссылке? Разве не адрес?
0
Evg
Эксперт CАвтор FAQ
18377 / 6424 / 441
Регистрация: 30.03.2009
Сообщений: 17,838
Записей в блоге: 28
20.06.2011, 13:05 #21
Цитата Сообщение от silentnuke Посмотреть сообщение
выведет
10
10
хотя смотрел по дебагу в памяти записано 100. Интересно особенности оптимизации mvs, или везде так, просто нет сейчас возможности проверить
Это оптимизация компилятора. Он верит модификатору const и во всех местах использования "p" в main заменяет её на 10. Т.е. в cout'ы отдаётся значение 10, хотя в функцию отдаётся указатель (ибо там уже ничего сделать нельзя) и по этому указателю успешно записывается 100
0
silentnuke
Android Programmer
139 / 140 / 5
Регистрация: 08.12.2010
Сообщений: 421
15.07.2011, 01:57 #22
окей, в продолжение темы, ещё немного магии, взываем функцию которая имеет принимаемые параметры, без параметров)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
 
void f(int a, int b)
{
    cout<<a+b<<endl;
}
 
void main()
{
    void (*p)();
    p=(void(*)())&f;
    (*p)();
}

Но то были цветочки, пойдем дальше)
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
#include <iostream>
using namespace std;
 
class A
{
protected:
    int a;
public:
    A(){a=10;}
};
 
class B:public A
{
    char *str;
public:
    B(){cout<<"constr\n";}
    void myfunc2()
    {
        str=new char[20];
        strcpy(str,"Hello World\n");
        cout<<str;
    }
};
 
void main()
{
    A* t=new A;
    B* tc=(B*)&t;
    tc->myfunc2();
}
Создали указатель базового класса, выделили память.
Создали указатель производного класса, привели базовый класс к классу наследнику.
И что же мы видим? У нас есть методы класса наследника, только большой вопрос откуда? ведь конструктор то не отработал, и как бы по идеи методов не должно быть, а так у нас есть и методы и поля наследника. и можно с ними работать....
0
An1ka
66 / 71 / 2
Регистрация: 30.06.2011
Сообщений: 176
15.07.2011, 05:25 #23
Цитата Сообщение от silentnuke Посмотреть сообщение
Создали указатель базового класса, выделили память.
Создали указатель производного класса, привели базовый класс к классу наследнику.
И что же мы видим? У нас есть методы класса наследника, только большой вопрос откуда? ведь конструктор то не отработал, и как бы по идеи методов не должно быть, а так у нас есть и методы и поля наследника. и можно с ними работать....
Методы - это просто функции, они создаются всегда один раз ( исключение шаблонные, там для каждого типа своя функция создается), которые одним параметром принимают указатель на вызывающий объект ( this).
0
Evg
Эксперт CАвтор FAQ
18377 / 6424 / 441
Регистрация: 30.03.2009
Сообщений: 17,838
Записей в блоге: 28
15.07.2011, 12:53 #24
Цитата Сообщение от silentnuke Посмотреть сообщение
окей, в продолжение темы, ещё немного магии, взываем функцию которая имеет принимаемые параметры, без параметров)
Ну вызовется у тебя функция с неинициализированными параметрами. И чего?

Цитата Сообщение от silentnuke Посмотреть сообщение
У нас есть методы класса наследника, только большой вопрос откуда?
Что есть метод на пальцах пояснял тут: раз (пост 11) и два (пост 23)
Там пояснял с другого угла зрения, но в данном случае должно быть то же самое

Добавлено через 23 минуты
silentnuke, касаемо твоего первого примера. В языке Си поддерживается "старый" стиль описания процедур (так называемый, традиционный стиль Кернигана-Ритчи). И там такое безобразие можно делать без всяких преобразований над указателями

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
void
func (str, i1, i2)
  const char *str;
  int i1;
  int i2;
{
  printf ("%s: i1=%d, i2=%d\n", str, i1, i2);
}
 
int
main (void)
{
  func ("first");
  func ("second", 10, 20);
  return 0;
}
что выдаст на исполнении что-то типа:

C
1
2
first: i1=1073784948, i2=1073830340
second: i1=10, i2=20
Или можно вообще вот так написать:

C
1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
int
main (void)
{
  printf ("%s: i1=%d, i2=%d\n", "first");
  printf ("%s: i1=%d, i2=%d\n", "second", 10, 20);
  return 0;
}
и получим точно такое же мусорное значение.

Все три примера (один твой и два моих) принципиально друг от друга ничем не отличаются. В них имеет место быть передача одного количества параметров, в то время как ожидалось другое количество. Правда в твоём случае дополнительно ожидался параметр-указатель другого типа (this)
0
kravam
быдлокодер
1703 / 890 / 45
Регистрация: 04.06.2008
Сообщений: 5,489
15.07.2011, 15:23 #25
Цитата Сообщение от silentnuke Посмотреть сообщение
окей, в продолжение темы, ещё немного магии, взываем функцию которая имеет принимаемые параметры, без параметров)
Я не силён в этом деле, но вообще вопрос конечно заслуживает удивления.
То, что компилится эта строчка- целиком пусть будет на совести авторов компилятора.
C++
1
        p=(void(*)())&f;
0
Evg
Эксперт CАвтор FAQ
18377 / 6424 / 441
Регистрация: 30.03.2009
Сообщений: 17,838
Записей в блоге: 28
15.07.2011, 15:51 #26
Цитата Сообщение от kravam Посмотреть сообщение
То, что компилится эта строчка- целиком пусть будет на совести авторов компилятора
А почему она должна не компилиться?
0
kravam
быдлокодер
1703 / 890 / 45
Регистрация: 04.06.2008
Сообщений: 5,489
15.07.2011, 17:03 #27
Потому, что p это void (*)();

а f имеет два аргумента
0
Evg
Эксперт CАвтор FAQ
18377 / 6424 / 441
Регистрация: 30.03.2009
Сообщений: 17,838
Записей в блоге: 28
15.07.2011, 17:15 #28
Цитата Сообщение от kravam Посмотреть сообщение
Потому, что p это void (*)();

а f имеет два аргумента
Программист явно поставил операцию преобразования над указателями. При любом явном преобразовании над указателями всегда считается, что программист "сам дурак" и компилятор снимает с себя всю ответственность за последствия. Никто же тебе не запрещает указатель на char приводить к указателю на int. А конструкция сия есть опасная, потому как, например, на машинах, где запрещены невыровненные обращения в память, работа с таким указателем может привести к слому программы. Если у тебя есть просто присваивание одного в другое, то компилятор ругнётся, а если явно вставлена операция преобразования типа - то компилятор молча это съест и переложит всю ответственность на программиста

Собственно, почему весь мир уже несколько десятков лет пытается создать защищённые системы программирования: потому что из-за бесконтрольной работы над указателями у людей постоянно возникают всякие скрытые проблемы и ошибки
0
silentnuke
Android Programmer
139 / 140 / 5
Регистрация: 08.12.2010
Сообщений: 421
15.07.2011, 17:21 #29
Evg, с первым случаем то все понятно, привел для ознакомления.)
больше второй случай интересный. с функцией ну ещё допустим понятно, она я так думаю создается в памяти один раз, дальше уже кидается адрес, но черт возьми откуда то указатель появился, мы же не создавали объект дочернего класса.
0
Evg
Эксперт CАвтор FAQ
18377 / 6424 / 441
Регистрация: 30.03.2009
Сообщений: 17,838
Записей в блоге: 28
15.07.2011, 17:28 #30
silentnuke, вся иерархия классов - оно точно так же опускается до уровня языка Си. В твоём случае мы имеем что-то типа:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct A
{
  int a;
};
 
struct B
{
  int a; /* это поле как бы пронаследовано из A */
  char *str;
};
 
...
struct A *a;
struct B *b;
 
a = malloc (sizeof (A));
b = (B*) &a;
...
Реально у тебя создался экземпляр класса A. Замет указатель на него трактуется как указатель на экземпляр B. При обращении к "b->str" номинально ты обращаешься в недопустимую память (поскольку память под это поле не выделялось в принципе). Но реально в конкретно данном случае у тебя код вряд ли где-то сломается. Причину этого объяснял здесь И снова malloc...
0
15.07.2011, 17:28
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.07.2011, 17:28
Привет! Вот еще темы с ответами:

Ссылки vs Указатели - C++
Почему ссылки считаются более хорошим средством, чем указатели? Ведь если человек будет использовать сторонние классы, он может не...

Указатели и ссылки - C++
Собственно, не могу до конца осознать как это работает, вот пример из вики(комменты входят в пример) int n = 6; // Объявление...

Ссылки и указатели - C++
Добрый день, не могу понять чем помогают при использовании указатели и ссылки? Есть код на c++ #progma once class well { ...

Указатели и ссылки - C++
Используя вместо самой переменной указатель на нее написать программу в соответствии с заданием: Вычислить y = cos|x3-x2|.


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

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

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