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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 169, средняя оценка - 4.97
Диман56
22 / 22 / 0
Регистрация: 07.11.2011
Сообщений: 154
#1

Понимание для чего вообще нужны указатели? - C++

12.11.2011, 20:12. Просмотров 23618. Ответов 112
Метки нет (Все метки)

Сейчас будет чистый мой тупняк. Слабонервным дальше не читать. Итак, для чего вообще нужны указатели? Я вот не пойму, зачем их надо было вообще придумывать??? Не понимаю их конкретной пользы, смысла. Кто-нибудь может по-человечески объяснить?
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.11.2011, 20:12
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Понимание для чего вообще нужны указатели? (C++):

Для чего нужны указатели? - C++
Кто может объяснить для чего нужны указатели и смысл их? в интернете одна муть и еще для чего нужно new delete

Для чего нужны указатели на функции? - C++
для чего нужны эти указатели на функции... не проще ли вызвать саму функцию, чем заводить под нее указатель и им пользоваться...

Ссылки и указатели, для чего нужны те и другие? - C++
Что такое ссылки? Что такое указатели? ДЛЯ чего служат те и другие?

Для чего нужны и зачем использовать smart-указатели? - C++
В Страуструпе не нашел, кто подскжает где можно про них прочитать ?)

Для чего нужны интерфейсы? - C++
Объясните на пальцах для чего нужны интерфейсы, как я понял они описывают методы и свойства, которые при наследовании классами должны были...

Указатели на слонов или А зачем нужны указатели? - C++
Знаю что таких вопросов было уйма, но я так и не нашел ответа на свой вопрос. Для чего нужны указатели? Что такое указатели я знаю, это...

112
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.11.2011, 06:07 #76
Цитата Сообщение от Bers Посмотреть сообщение
/зы У меня 90% всех ошибок связано с указателями. Если что-то где то упало в рантайме, то скорее всего оно упало по вине некорректного использования указателя.
У меня на 20 000 ошибок 19 999 в паскале и оказываются выходом за пределы массива, оставшаяся одна - или алгоритмическая ошибка, или очепятка в каком нибудь идентификаторе. И никогда не было ошибок, связанных с указателями, даже когда я толкьо начинал учиться программировать, причём самостоятельно.

Добавлено через 2 минуты
Цитата Сообщение от Bers Посмотреть сообщение
Не понял к чему это было сказано.
К тому, что только чайник способен во внутреннем поле одного объекта хранить указатель на внешний объект другого класса. И то не всякий. Ктому, что прочитав твой код класса A, я чуть не заорал в слух: "Ересь!".
0
Bers
Заблокирован
15.11.2011, 06:12 #77
Цитата Сообщение от taras atavin Посмотреть сообщение
К тому, что только чайник способен во внутреннем поле одного объекта хранить указатель на внешний объект другого класса.
Смысл хранить указатель на внутренний объект?
Внутри проще хранить сами объекты.

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

А голый указатель, оказавшийся "на другой стороне" становится потенциально опасным.
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.11.2011, 06:22 #78
Цитата Сообщение от Bers Посмотреть сообщение
как определить валидный указатель, или уже нет.
По значению самого указателя: если он не валиден, то равен NULL. Поэтому то и можно хранить в полях только два вида указателей:
1. Перкрёстные на свой класс.
2. на подчинённые объекты.
Иначе объект B не знает, где треубуется записать тот самый NULL.

Добавлено через 2 минуты
Цитата Сообщение от Bers Посмотреть сообщение
Смысл хранить указатель на внутренний объект? Внутри проще хранить сами объекты.
А если твой класс - класс ограниченного, динамического, или разреженного массива? А если твой объект содержит динамический массив в числе других полей? А если объект A должен создать в своём поле объект толи базового класса B, толи одного из известных на этапе разработки классса A классов, производных от B, но конкретный фактический класс санет известен только на этапе исполнения? unionы, конечно, ни кто не отменял, а если у одного из производных классов ещё и sizeof больше на пару сотен килобайт, а сам экземпляр A ещё и в массиве из нескольких сотен тысяч элментов? И ты забываешь о самом интересном назначении указателей - реализации процедурных типов через типы указателей на функции.

Добавлено через 4 минуты
Цитата Сообщение от Bers Посмотреть сообщение
Указатель и нужен собственного говоря, для того, что бы знание об объекте передать куда то ещё - вызывающей стороне, или в вызываемую сторону.
Передать объект по указаетлю для использхзования этого указателя внутри функции при однократном её исполнении - это одно, а хранить указатель на внешнйи объект - совсем другое. В первом случае управление имеет объект A и ни кто другой не может удалить объект B, но и объект A не должен этого делать, так что лучше передавать по ссылке, но если понимаешь, как можно, а как нельзя обращаться с чужими указателями, то можно и по указателю. Во втором же случае ты теряешь контроль.
0
Bers
Заблокирован
15.11.2011, 06:25 #79
taras atavin, реальный пример: библиотека DevIL
Загружает картинку, а наружу выдаёт указатель на массив цветов пикселей этой картинки.

Получив этот указатель себе в руки, можно делать с внутренними данными Девила все что угодно. Например, сделать им delete. Результат - крэш при де_инициализации Девила.


Другой пример: Пользователь просит менеджера создать ему девайс. Менеджер создаёт девайс, а наружу (пользователю) в руки предоставляет ИНТЕРФЕЙСНЫЙ УКАЗАТЕЛЬ.

Не указатель. А особый объект "интерфейсный указатель". С помощью которого пользователь сможет пользоваться внутренним объектом менеджера. Но не сможет его никак поломать.

Зачем самому менеджеру хранить указатель на свои объекты - этого я понять не могу. Зачем хранить указатели, когда можно хранить сами объекты?

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

Выдай наружу указатель на приватные данные, и можешь считать, что они стали публичными.
Выдай наружу специализированный интерфейс - и считай, что проблема жизни и смерти объекта осталась проблемой владельца, и никого более.
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.11.2011, 06:39 #80
Кстати, раз уж любишь такие указатели, то вот тебе ещё пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class B
{
 ...// вообще не важно, что здесь валяется
};
class A
{
 public: A(B& x); // Пока всё выглядит нормально
};
A::A(B& x) // Эту часть засовываем в статическую библиотеку, а с проектом связываем бинарник
{
 B *y;
 y=&x;
 delete y;
}
. Надеюсь не будешь оспаривать, что сочинить эту мину можно только специально?

Добавлено через 2 минуты
Цитата Сообщение от Bers Посмотреть сообщение
Получив этот указатель себе в руки, можно делать с внутренними данными Девила все что угодно. Например, сделать им delete. Результат - крэш при де_инициализации Девила.
Девелоперы библиотеки подумать не могли, что ты будешь делитить чужой указатель.
0
Bers
Заблокирован
15.11.2011, 06:47 #81
Цитата Сообщение от taras atavin Посмотреть сообщение
Девелоперы библиотеки подумать не могли, что ты будешь делитить чужой указаетль.
Дело не в том, о чем думали девелоперы библиотеки. Дело в том, что грамотный класс инвариантен. Его нельзя сломать снаружи.

Если класс не_инвариантен, значит он зависим от того, насколько корректно его использует вызывающая сторона. А в большом проекте , где Вася может быть не в курсе, чего делает Петя, это означает потенциальная возможность заложить мину замедленного действия. и даже не заметить этого.

Если класс не инкапсулирует в себе свою зону отвественности, и успех его работоспособности зависит от корректности вызывающей стороны - такая система ненадёжна. В такой системе программистам потребуется больше времени тратить на исправления ошибок, тестирование, отладку, и тп.
0
Евгений М.
1036 / 977 / 54
Регистрация: 28.02.2010
Сообщений: 2,829
Завершенные тесты: 2
15.11.2011, 06:52 #82
Пожалуй приведу пример решения одной задачи, где я использовал указатели. Может быть существует другой способ решения, который я не знал.
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
class OData
{
public:
 
    // ...
 
    //
    // Все следующее нужно переопределять для различных типов графика
    //
 
    // для определения "нужна ли данная или нет"
    virtual bool isRequiredData()=0;
 
    // события. возникающие при чтении таблицы
    virtual void onDataBegin()=0;
    virtual void onDataFinish()=0;
    virtual void onTimeChanged()=0;
 
    // запоминаем то, что нужно
    virtual void postFoundData(const char* value)=0;
 
    // ввод параметров критерии
    // ВНИМАНИЕ: количество параметров проверяется до вызова
    virtual void input(double*)=0;
};
 
class ODataTime: public OData
{
protected:
    // параметры критерий
    double x, y, z;
 
public:
    ODataTime(std::string& _dataFilename, std::string& _ylabel, unsigned int _valueColumn, unsigned int _commandNumber):
      OData(_dataFilename, _ylabel, _valueColumn, _commandNumber) {};
 
    // для определения "нужна ли данная или нет"
    bool isRequiredData();
 
    // события. возникающие при чтении таблицы
    void onDataBegin();
    void onDataFinish();
    void onTimeChanged();
 
    // запоминаем то, что нужно
    void postFoundData(const char* value);
 
    // ввод параметров критерии
    void input(double*);
};
 
class ODataRho: public OData
{
protected:
    // параметры критерий
    // начало отрезка
    double x1, y1, z1;
 
    // конец отрезка
    double x2, y2, z2;
 
    // нужное время
    double t1;
 
    // то что собрали
    // массив пар [расстояние, величина]
    std::vector< std::pair<double, const char*> > aRhoValue;
 
    // допольнительные функции
    double rho(double, double, double);
 
    // для определения принадлежности отрезку
    bool isBelongToInterval();
 
public:
 
    ODataRho(std::string& _dataFilename, std::string& _ylabel, unsigned int _valueColumn, unsigned int _commandNumber):
      OData(_dataFilename, _ylabel, _valueColumn, _commandNumber) {};
 
    // для определения "нужна ли данная или нет"
    bool isRequiredData();
 
    // события. возникающие при чтении таблицы
    void onDataBegin();
    void onDataFinish();
    void onTimeChanged();
 
    // запоминаем то, что нужно
    void postFoundData(const char* value);
 
    // ввод параметров критерии
    void input(double*);
};
C++
1
2
3
4
5
6
7
8
9
namespace global
{
    //...
 
    static IData* idata; // входные данные
    static std::vector< OData* > odatas; // выходные
 
    // ...
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// обработка данных, полученой из строки
for (unsigned int j=0; j<odatas.size(); j++)
{
    odata = odatas[j];
 
    // если полученые данные из узла - то что нужно
    if (odata->isRequiredData()==true)
    {
        odata->foundRequiredData = true;
 
        r = idata->readValue(odata->valueColumn, value);
        if (r==false)
            return -1;
 
        // то записываем их
        odata->postFoundData(value);
 
    }
}
В векторе odatas содержатся указатели на объекты класса ODataTime и ODataRho. Реализация функции isRequiredData у каждого своя со своими "параметрами критерий". Проверяемые данные находятся в idata из пространства global.
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.11.2011, 07:03 #83
Цитата Сообщение от Bers Посмотреть сообщение
Дело не в том, о чем думали девелоперы библиотеки. Дело в том, что грамотный класс инвариантен. Его нельзя сломать снаружи.
Читай начало поста № 80.
0
Bers
Заблокирован
15.11.2011, 07:05 #84
Цитата Сообщение от taras atavin Посмотреть сообщение
Читай начало поста № 80.
Прочитал. И?
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.11.2011, 07:23 #85
Цитата Сообщение от Bers Посмотреть сообщение
Если класс не инкапсулирует в себе свою зону отвественности, и успех его работоспособности зависит от корректности вызывающей стороны - такая система ненадёжна. В такой системе программистам потребуется больше времени тратить на исправления ошибок, тестирование, отладку, и тп.
При построении дерева указатели реально нужны, но класс дерева полностью их инкапсулирует и наружу не выдаёт. Динамический массив нельзя сделать без указателей явных, или скрытых, но класс динамического массива полностью инкапсулирует свой укказатель на данные и наружу не выдаёт.
Цитата Сообщение от Bers Посмотреть сообщение
Прочитал. И?
Обратил внимание на комментарий в калссе B и на реализацию конструктора класса A? Мораль же всей басни такова: указатели необходимы, без них нельзя сделать ничего, кроме калькулятора, но используя их, надо все указатели, кроме указателей на функции, прятать в pirvate полях и наружу не выдавать, классы же должны иметь понятные и хорошо документированные интерфейсы. Нельзя использовать то, чего не понимаешь, а если возникает такая необходимость - пиши хоть тестовые примеры, но сначала изучи, а потом реально используй, а не наоборот.
0
Bers
Заблокирован
15.11.2011, 07:25 #86
Цитата Сообщение от taras atavin Посмотреть сообщение
При построении дерева указатели реально нужны, но класс дерева полностью их инкапсулирует и наружу не выдаёт. Динамический массив нельзя сделать без указателей явных, или скрытых, но класс динамического массива полностью инкапсулирует свой укказатель на данные и наружу не выдаёт.
Вы понимаете, что втолковываете мне очевидные для меня вещи?
Я прекрасно это все знаю. И где можно использовать, и где нельзя.

Я вам говорю - нельзя в любой момент времени лазить по указателю. Можно тогда, и только тогда, когда есть 100% гарантия валидности указателя.

Вот вам ещё реальный случай: большой проект, над которым работало несколько человек.
Менеджер держал свои объекты в векторе. А наружу выдавал интерфейсный указатель на эти объекты. Что бы снаружи нельзя было поломать объекты через указатель.

Казалось бы - все круто. Все нормально. Проблемм быть не должно.

Переодически крэш всей системы. Причём каждый раз в разных местах. Причем не постоянно, а довольно таки редко. Даже не понятно, что является причиной аварий. Трудно найти баг, который проявляется лишь изредка, причем каждый раз в разных местах.

И только потом, после многодневных поисков, и отчаянного тестирования, выяснилось.
Внимание: когда заканчивался резерв памяти вектора, он делал реалок. Все внешние ссылки на объекты становились не_валидными.

Но поскольку, это происходило только когда у вектора заканчивался резерв памяти, то происходило это не постоянно, а только через раз.

А интерфейсный указатель об этом не знал. Никому в голову не приходило, что объект, который по замыслу не должен вообще никуда двигаться, может поменять своё место жительство.

Программист допустил ошибку. Он либо должен был юзать list вместо vector
Либо интерфейсный указатель должен был обращаться к объекту по индексу массива (им не страшны реалоки), а не по указателю напрямую.

Но это была ошибка, которую искали несколько дней.

Допустить такую ошибку очень просто. А если ещё у вас при этом классы сами не будут следить за собственной безопасностью, а уповать на корректность программистов, то количество таких багов вырастет в геометрической прогрессии.
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.11.2011, 07:30 #87
Цитата Сообщение от Bers Посмотреть сообщение
Я вам говорю - нельзя в любой момент времени лазить по указателю. Можно тогда, и только тогда, когда есть 100% гарантия валидности указателя.
Ты думаешь, я этого не понимаю? А теперь прикинь:
C++
1
2
3
4
5
6
7
8
#include <windows.h>
.... *p=NULL;
...
 ... WinMain (...)
{
 ...
 delete [] p; // Освобождается только сдесь, при выделении проверяется, если NULL, то сразу WM_CLOSE.
}
. В каком месте его нельзя использовать? При том, что я нарушил своё же правило прятать указатели в private.
0
Bers
Заблокирован
15.11.2011, 07:31 #88
Цитата Сообщение от taras atavin Посмотреть сообщение
В каком месте его нельзя использовать? При том, что я нарушил своё же правило прятать указатели в private.
я не понял смысла приведенного псевдокода
0
taras atavin
3570 / 1753 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.11.2011, 07:49 #89
Цитата Сообщение от Bers Посмотреть сообщение
обращаться к объекту по индексу массива
Указатели внутырь массива вычисляю только для однократного использования, а из перегпруженных опреторов [] возвращаю только ссылки. Причём, если массив динамический, то сначала обращаюсь к методу, возвращающему число элементов, а только потом использую индексы.

Добавлено через 2 минуты
Цитата Сообщение от Bers Посмотреть сообщение
я не понял смысла приведенного псевдокода
А смысл в том, в таком коде после выделения памяти гарантия существования данныхз и валидности указателя есть всегда. И обращаться к данным по указателю можно когда угодно. Торопился, забыл вместо
C++
1
delete [] p;
C++
1
2
3
4
if (p)
 {
  delete [] p;
 }
, в реальном коде такого не допусакаю, а только в примерах.

Добавлено через 6 минут
Цитата Сообщение от Bers Посмотреть сообщение
А если ещё у вас при этом классы сами не будут следить за собственной безопасностью, а уповать на корректность программистов,
Пост № 80!
0
Bers
Заблокирован
15.11.2011, 07:51 #90
Цитата Сообщение от taras atavin Посмотреть сообщение
В каком месте его нельзя использовать? При том, что я нарушил своё же правило прятать указатели в private.
Цитата Сообщение от taras atavin Посмотреть сообщение
А смысл в том, в таком коде после ввыделения памяти гарантия существования указателя есть всегда.
Если вы гарантируете, что объект жив - значит никто его убить без вашего позволения не сможет.
Голому указателю в любой точке программы можно сделать delete
Что мне помешает убить данные по указателю?

Добавлено через 1 минуту
Цитата Сообщение от taras atavin Посмотреть сообщение
Пост № 80!
Не вижу никакой связи между темой инварианта класса, и 80м постом
0
15.11.2011, 07:51
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.11.2011, 07:51
Привет! Вот еще темы с ответами:

Для чего нужны callback-функции - C++
Для чего нужны callback-функции? И можно привести какой-нибуль пример по их использованию.

Для чего нужны вложенные структуры? - C++
Скажите пожалуйста для чего нужны вложенные структуры и где их используют?

для чего нужны хеш таблицы? - C++
для чего нужны хеш таблицы? если есть массивы )

try catch throw для чего нужны? - C++
Для чего нужны эти операторы? Линканите пожалуйста статью, где доходчиво объяснено их применение, в разных вариантах (например я видел...


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

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

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