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

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

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

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

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

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

C++ Указатели и ссылки
C++ Ссылки и указатели
C++ Указатели и ссылки [С++]
Указатели и Ссылки C++
Ссылки vs Указатели C++
C++ Указатели и ссылки
Указатели и ссылки? C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Evg
Эксперт CАвтор FAQ
17304 / 5552 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
20.06.2011, 13:05     Ссылки и указатели #21
Цитата Сообщение от silentnuke Посмотреть сообщение
выведет
10
10
хотя смотрел по дебагу в памяти записано 100. Интересно особенности оптимизации mvs, или везде так, просто нет сейчас возможности проверить
Это оптимизация компилятора. Он верит модификатору const и во всех местах использования "p" в main заменяет её на 10. Т.е. в cout'ы отдаётся значение 10, хотя в функцию отдаётся указатель (ибо там уже ничего сделать нельзя) и по этому указателю успешно записывается 100
silentnuke
Android Programmer
138 / 139 / 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();
}
Создали указатель базового класса, выделили память.
Создали указатель производного класса, привели базовый класс к классу наследнику.
И что же мы видим? У нас есть методы класса наследника, только большой вопрос откуда? ведь конструктор то не отработал, и как бы по идеи методов не должно быть, а так у нас есть и методы и поля наследника. и можно с ними работать....
An1ka
65 / 70 / 2
Регистрация: 30.06.2011
Сообщений: 176
15.07.2011, 05:25     Ссылки и указатели #23
Цитата Сообщение от silentnuke Посмотреть сообщение
Создали указатель базового класса, выделили память.
Создали указатель производного класса, привели базовый класс к классу наследнику.
И что же мы видим? У нас есть методы класса наследника, только большой вопрос откуда? ведь конструктор то не отработал, и как бы по идеи методов не должно быть, а так у нас есть и методы и поля наследника. и можно с ними работать....
Методы - это просто функции, они создаются всегда один раз ( исключение шаблонные, там для каждого типа своя функция создается), которые одним параметром принимают указатель на вызывающий объект ( this).
Evg
Эксперт CАвтор FAQ
17304 / 5552 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
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)
kravam
быдлокодер
1696 / 875 / 44
Регистрация: 04.06.2008
Сообщений: 5,342
15.07.2011, 15:23     Ссылки и указатели #25
Цитата Сообщение от silentnuke Посмотреть сообщение
окей, в продолжение темы, ещё немного магии, взываем функцию которая имеет принимаемые параметры, без параметров)
Я не силён в этом деле, но вообще вопрос конечно заслуживает удивления.
То, что компилится эта строчка- целиком пусть будет на совести авторов компилятора.
C++
1
        p=(void(*)())&f;
Evg
Эксперт CАвтор FAQ
17304 / 5552 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
15.07.2011, 15:51     Ссылки и указатели #26
Цитата Сообщение от kravam Посмотреть сообщение
То, что компилится эта строчка- целиком пусть будет на совести авторов компилятора
А почему она должна не компилиться?
kravam
быдлокодер
1696 / 875 / 44
Регистрация: 04.06.2008
Сообщений: 5,342
15.07.2011, 17:03     Ссылки и указатели #27
Потому, что p это void (*)();

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

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

Собственно, почему весь мир уже несколько десятков лет пытается создать защищённые системы программирования: потому что из-за бесконтрольной работы над указателями у людей постоянно возникают всякие скрытые проблемы и ошибки
silentnuke
Android Programmer
138 / 139 / 5
Регистрация: 08.12.2010
Сообщений: 421
15.07.2011, 17:21     Ссылки и указатели #29
Evg, с первым случаем то все понятно, привел для ознакомления.)
больше второй случай интересный. с функцией ну ещё допустим понятно, она я так думаю создается в памяти один раз, дальше уже кидается адрес, но черт возьми откуда то указатель появился, мы же не создавали объект дочернего класса.
Evg
Эксперт CАвтор FAQ
17304 / 5552 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
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...
kravam
быдлокодер
1696 / 875 / 44
Регистрация: 04.06.2008
Сообщений: 5,342
15.07.2011, 17:46     Ссылки и указатели #31
Evg, странно. Ты спрашиваешь что неверно с МОЕЙ Точки зрения. А опровергаешь её с точки зрения создателей компилятора.
...Так-то мне понятны причины, по которым это компилится. Понятны но неубедительны.
Evg
Эксперт CАвтор FAQ
17304 / 5552 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
15.07.2011, 17:48     Ссылки и указатели #32
Цитата Сообщение от kravam Посмотреть сообщение
Evg, странно. Ты спрашиваешь что неверно с МОЕЙ Точки зрения. А опровергаешь её с точки зрения создателей компилятора.
...Так-то мне понятны причины, по которым это компилится. Понятны но неубедительны.
Да я вроде бы ничего не спрашивал и ничего не опровергал... Во всяком случае, я так и не понял, о чём ты
kravam
быдлокодер
1696 / 875 / 44
Регистрация: 04.06.2008
Сообщений: 5,342
15.07.2011, 17:54     Ссылки и указатели #33
Evg, ОК
Тогда я так спрошу: тебе непонятно недоумение человека, который считает, что не должно компилиться присваивание указателю на функцию, не принимающую аргументов, адреса функции, принимающей два аргумента?
silent_1991
Эксперт С++
4952 / 3028 / 149
Регистрация: 11.11.2009
Сообщений: 7,026
Завершенные тесты: 1
15.07.2011, 18:00     Ссылки и указатели #34
Цитата Сообщение от kravam Посмотреть сообщение
тебе непонятно недоумение человека, который считает, что не должно компилиться присваивание указателю на функцию, не принимающую аргументов, адреса функции, принимающей два аргумента?
Мне непонятно. Ибо такое присваивание и не будет компилироваться. А вот присваивание с предварительным приведением будет. Потому что производители дрелей производят их для строительных работ и не несут ответа за какого-то чудака, который этой дрелью просверлит себе голову.
kravam
быдлокодер
1696 / 875 / 44
Регистрация: 04.06.2008
Сообщений: 5,342
15.07.2011, 18:02     Ссылки и указатели #35
Цитата Сообщение от silent_1991 Посмотреть сообщение
Ибо такое присваивание и не будет компилироваться.
компилится, шеф
Evg
Эксперт CАвтор FAQ
17304 / 5552 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
15.07.2011, 18:03     Ссылки и указатели #36
Цитата Сообщение от kravam Посмотреть сообщение
Evg, ОК
Тогда я так спрошу: тебе непонятно недоумение человека, который считает, что не должно компилиться присваивание указателю на функцию, не принимающую аргументов, адреса функции, принимающей два аргумента?
Нет. Недоумения у меня не было. Ты сказал "но вообще вопрос конечно заслуживает удивления", а своим вопросом я попытался выяснить у тебя, почему это заслуживает удивления. Такой код заведомо корректный с точки зрения языка, т.е. компилятор должен его проглотить, не моргнув.
silent_1991
Эксперт С++
4952 / 3028 / 149
Регистрация: 11.11.2009
Сообщений: 7,026
Завершенные тесты: 1
15.07.2011, 18:04     Ссылки и указатели #37
kravam, мне компилятор в ответ на скармливание такого кода:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
void f(int a, int b)
{
        std::cout << a + b << std::endl;
}
 
int main()
{
    void (*p)();
 
    p = /*(void (*)())*/&f;
    
    (*p)();
 
    return 0;
}
говорит про невозможность преобразования void (*)(int, int) в void (*)(void).
Evg
Эксперт CАвтор FAQ
17304 / 5552 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
15.07.2011, 18:08     Ссылки и указатели #38
Цитата Сообщение от kravam Посмотреть сообщение
компилится, шеф
В Си++ такое НЕ компилится

C++
1
2
3
4
5
6
7
8
extern void func (int, int);
 
int main (void)
{
  void (*p)(void);
  p = &func;
  return 0;
}
потому что справа и слева от присваивания стоят указатели несовместимых типов. Но если поставить операцию преобразования (т.е. 5-ю строку заменить на "p = (void (*)(void)) &func;"), то всё будет нормально
silentnuke
Android Programmer
138 / 139 / 5
Регистрация: 08.12.2010
Сообщений: 421
15.07.2011, 18:10     Ссылки и указатели #39
Evg, спасибо, со вторым случае стало хоть более менее понятно.)
я так понял то что я привел класс A к наследнику тут вообще не причем, у нас поля стали доступны уже при создании указателя класса наследника.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.07.2011, 18:12     Ссылки и указатели
Еще ссылки по теме:

Указатели и ссылки C++
C++ Указатели и ссылки c++
Указатели и ссылки C++
C++ Ссылки, указатели
Ссылки и указатели C++

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

Или воспользуйтесь поиском по форуму:
Evg
Эксперт CАвтор FAQ
17304 / 5552 / 347
Регистрация: 30.03.2009
Сообщений: 15,112
Записей в блоге: 26
15.07.2011, 18:12     Ссылки и указатели #40
Цитата Сообщение от silentnuke Посмотреть сообщение
у нас поля стали доступны уже при создании указателя класса наследника
Они стали доступны с точки зрения языка. Но компилятор при этом не знает, выделена под них память, или нет. И это находится в твоей ответственности (потому как ты сделал преобразование типа над указателями)
Yandex
Объявления
15.07.2011, 18:12     Ссылки и указатели
Ответ Создать тему
Опции темы

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