22 / 22 / 4
Регистрация: 07.11.2011
Сообщений: 154
1

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

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

Author24 — интернет-сервис помощи студентам
Сейчас будет чистый мой тупняк. Слабонервным дальше не читать. Итак, для чего вообще нужны указатели? Я вот не пойму, зачем их надо было вообще придумывать??? Не понимаю их конкретной пользы, смысла. Кто-нибудь может по-человечески объяснить?
1
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.11.2011, 20:12
Ответы с готовыми решениями:

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

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

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

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

112
Заблокирован
15.11.2011, 06:47 81
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от taras atavin Посмотреть сообщение
Девелоперы библиотеки подумать не могли, что ты будешь делитить чужой указаетль.
Дело не в том, о чем думали девелоперы библиотеки. Дело в том, что грамотный класс инвариантен. Его нельзя сломать снаружи.

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

Если класс не инкапсулирует в себе свою зону отвественности, и успех его работоспособности зависит от корректности вызывающей стороны - такая система ненадёжна. В такой системе программистам потребуется больше времени тратить на исправления ошибок, тестирование, отладку, и тп.
0
1080 / 1007 / 106
Регистрация: 28.02.2010
Сообщений: 2,889
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
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
15.11.2011, 07:03 83
Цитата Сообщение от Bers Посмотреть сообщение
Дело не в том, о чем думали девелоперы библиотеки. Дело в том, что грамотный класс инвариантен. Его нельзя сломать снаружи.
Читай начало поста № 80.
0
Заблокирован
15.11.2011, 07:05 84
Цитата Сообщение от taras atavin Посмотреть сообщение
Читай начало поста № 80.
Прочитал. И?
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
15.11.2011, 07:23 85
Цитата Сообщение от Bers Посмотреть сообщение
Если класс не инкапсулирует в себе свою зону отвественности, и успех его работоспособности зависит от корректности вызывающей стороны - такая система ненадёжна. В такой системе программистам потребуется больше времени тратить на исправления ошибок, тестирование, отладку, и тп.
При построении дерева указатели реально нужны, но класс дерева полностью их инкапсулирует и наружу не выдаёт. Динамический массив нельзя сделать без указателей явных, или скрытых, но класс динамического массива полностью инкапсулирует свой укказатель на данные и наружу не выдаёт.
Цитата Сообщение от Bers Посмотреть сообщение
Прочитал. И?
Обратил внимание на комментарий в калссе B и на реализацию конструктора класса A? Мораль же всей басни такова: указатели необходимы, без них нельзя сделать ничего, кроме калькулятора, но используя их, надо все указатели, кроме указателей на функции, прятать в pirvate полях и наружу не выдавать, классы же должны иметь понятные и хорошо документированные интерфейсы. Нельзя использовать то, чего не понимаешь, а если возникает такая необходимость - пиши хоть тестовые примеры, но сначала изучи, а потом реально используй, а не наоборот.
0
Заблокирован
15.11.2011, 07:25 86
Цитата Сообщение от taras atavin Посмотреть сообщение
При построении дерева указатели реально нужны, но класс дерева полностью их инкапсулирует и наружу не выдаёт. Динамический массив нельзя сделать без указателей явных, или скрытых, но класс динамического массива полностью инкапсулирует свой укказатель на данные и наружу не выдаёт.
Вы понимаете, что втолковываете мне очевидные для меня вещи?
Я прекрасно это все знаю. И где можно использовать, и где нельзя.

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

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

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

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

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

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

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

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

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

Допустить такую ошибку очень просто. А если ещё у вас при этом классы сами не будут следить за собственной безопасностью, а уповать на корректность программистов, то количество таких багов вырастет в геометрической прогрессии.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
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
Заблокирован
15.11.2011, 07:31 88
Цитата Сообщение от taras atavin Посмотреть сообщение
В каком месте его нельзя использовать? При том, что я нарушил своё же правило прятать указатели в private.
я не понял смысла приведенного псевдокода
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
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
Заблокирован
15.11.2011, 07:51 90
Цитата Сообщение от taras atavin Посмотреть сообщение
В каком месте его нельзя использовать? При том, что я нарушил своё же правило прятать указатели в private.
Цитата Сообщение от taras atavin Посмотреть сообщение
А смысл в том, в таком коде после ввыделения памяти гарантия существования указателя есть всегда.
Если вы гарантируете, что объект жив - значит никто его убить без вашего позволения не сможет.
Голому указателю в любой точке программы можно сделать delete
Что мне помешает убить данные по указателю?

Добавлено через 1 минуту
Цитата Сообщение от taras atavin Посмотреть сообщение
Пост № 80!
Не вижу никакой связи между темой инварианта класса, и 80м постом
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
15.11.2011, 08:23 91
Цитата Сообщение от Bers Посмотреть сообщение
Не вижу никакой связи между темой инварианта класса, и 80м постом
А связь в том, что я сочинил инвариантную мину. От класса B она вообще не зависит.

Добавлено через 4 минуты
Цитата Сообщение от Bers Посмотреть сообщение
Если вы гарантируете, что объект жив - значит никто его убить без вашего позволения не сможет. Голому указателю в любой точке программы можно сделать delete Что мне помешает убить данные по указателю?
Ни чего, но если ты заранее решил убить объект в единственном месте при завершении программы, своего решения не менял, а прогу написал один, то про себя ты знаешь, что ни где в программе неожиджанного освобождения нет по факту, а это и есть гарантия. Но лучше так не делать.
0
Заблокирован
15.11.2011, 08:25 92
Цитата Сообщение от taras atavin Посмотреть сообщение
А связь в том, что я сочинил инвариантную мину. От класса B она вообще не зависит.
Там один объект принимает на входе знание о другом объекте. И убивает его.
Причем снаружи объект "как бы жив". Он не знает, что его уже убили.

Не понятно, а при чем тут инвариант?

Инвариант класса, это свойство класса, при котором работа класса не зависит от корректности вызывающей стороны.

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

Так же, он не кидает исключений, за исключением исключительных ситуаций.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
15.11.2011, 08:26 93
Цитата Сообщение от Bers Посмотреть сообщение
Инвариант класса, это свойство класса,
Инвариантность придумана не айтишниками, означает независимость ни от каких условий, моя мина ни от чего не зависит.
0
Заблокирован
15.11.2011, 08:36 94
Цитата Сообщение от taras atavin Посмотреть сообщение
Ни чего, но если ты заранее решил убить объект в единственном месте при завершении программы, своего решения не менял, а прогу написал один, то про себя ты знаешь, что ни где в программе неожиджанного освобождения нет по факту, а это и есть гарантия. Но лучше так не делать.
Это не гарантия. Это устное, ничем не подкрепленное соглашение.
Ошибки в программах возникают по ничайности в непредсказуемых для самих программистов местах.

Сделали класс, протестировали.
А что значит протестировать? Значит погонять все методы класса со всеми возможными аргументами. Самыми кривыми. И посмотреть, как класс будит справляться.

Но если осталась лазейка, через которую сможет забраться баг, то по теории ошибок именно через эту лазейку он туда и залезет.

Если программист думает: "клянусь! Что никогда не буду кормить классу указатели объектов созданных на стеке!" То это означает, что когда нибудь его класс обязательно крякнет именно потому, что он допустил устное соглашение, но не дал никаких гарантий.

Вот у меня был случай: сделал шаблонный низко-уровневый класс. И протестировал его вроде бы. Потом уже делал домашний проектик, и оказалось что в этом низко-уровневом классе есть баг (не качественно протестировал. Поленился)

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

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

И только потом опять запускал основной проект, где уже запускалась исправленная версия класса. И уже смотрел, устранилась ли проблема, или нет.


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

Потратил бы на 10 минут больше времени на тестирование, мне не пришлось бы потом тратить 3 часа на поиски проблемы в более крупном проекте.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
15.11.2011, 10:50 95
Цитата Сообщение от Bers Посмотреть сообщение
Ошибки в программах возникают по ничайности в непредсказуемых для самих программистов местах
Согласен. Но не такие же! Я умудряюсь не тратить время на отладку конкретно по указателям и адресации на их основе, даже работая с линейным массивом, как с неявно-двумерным и пересчитывая индексы не уровнем ниже в классе-контейнере, а непосредственно в функции, реализующей сам алгоритм, да ещё и навесив на него там же сразу два блочных кода, но вылетать за пределы массива сотни, а часто и более тысячи раз на одном проекте по индексам.
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
15.11.2011, 11:22 96
Bers, В мире не все идеально. И работа с указателями не сложна. Если не делать подобных вещей.

C++
1
2
3
4
5
6
7
int main()
{
   std::string s = "hello";
   std::cout << s << std::endl;
   delete[] s.c_str();
   delete[] s.data();
}
0
Заблокирован
15.11.2011, 11:59 97
Цитата Сообщение от ForEveR Посмотреть сообщение
delete[] s.c_str();
За совместимость с СИ, с++ пришлось заплатить свою цену.

Но если стандартный стринг нарушает инкапсуляцию во имя совместимости с си, это не значит, что нужно брать с него пример, и в оо-архитектуре нарушать инкапсуляцию каждый раз, когда захочется слентяйничать и сделать "быстро и сердито"
0
Higher
1953 / 1219 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
15.11.2011, 13:05 98
Цитата Сообщение от taras atavin Посмотреть сообщение
Обёртка, которую не понимаешь, опасна, в отличие от указателя.
Опасна? о_О
Цитата Сообщение от taras atavin Посмотреть сообщение
ну так она и так не утечёт
Вполне утечет.
Забыл написать деструктор - утечка.
Забыл написать оператор присваивания - утечка + UB.
И еще куча вариантов.

Цитата Сообщение от taras atavin Посмотреть сообщение
зато с непонятной обёрткой ты наделаешь много других делов ещё опаснее любой утечки
Обертка как раз не позволяет делать опасные вещи.


Цитата Сообщение от taras atavin Посмотреть сообщение
Ну ка приведи пример прикладной задачи, в которой бы это не понадобилось.
Первое что пришло в голову - вывести все файлы в текущей папке.
Правда это скорее системная задача, но указателям там разумного применения нету.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
15.11.2011, 13:24 99
Цитата Сообщение от diagon Посмотреть сообщение
Забыл написать деструктор - утечка.
И как же его можно умудрится забыть написать?

Добавлено через 6 минут
Цитата Сообщение от diagon Посмотреть сообщение
Первое что пришло в голову - вывести все файлы в текущей папке.
Ни одна прилада самостоятельно список файлов не выводит. Да и не задача это, а подзадача. А ты приведи пример целиком задачи, решение которой могло бы иметь самостоятельную практическую ценность отдельно от других прибамбасов (за исключением ОС и самого компьютера) и при этом могло бы быть получено без указателей в какой бы то ни было части программы, включая и те, что решают подзадачи и зовутся подпрограммами. Только не говори "повторить блокнот, используя TMemo", или "Сделать растровый криворедактор на базе TImage" - это не прикладные, а скорей учебные задачи. В любой же реальной задаче будет текст, состящий из заранее не известного числа не только символов, но и строк, заранее не известный размер статистической выборки, или матрицы коэффициентов системы уравнений, математическое выражение неизвестной длины или ещё какая пакость, требующая динамического выделения памяти. И на все подзадачи ты просто не найдёшь готовых библиотек, а среди нерешаемых библиотеками хоть и нет гарантии встретить подзадачу, для которой понадобится явный указатель, но нет и обратной гарантии.
0
Higher
1953 / 1219 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
15.11.2011, 13:29 100
Цитата Сообщение от taras atavin Посмотреть сообщение
И как же его можно умудрится забыть написать?
Мало ли. Забыл, опечатался = утечка. Все совершают ошибки, вот только с использованием чистых указателей их иногда довольно проблематично найти.

Цитата Сообщение от taras atavin Посмотреть сообщение
А ты приведи пример целиком задачи, решение которой могло бы иметь самостоятельную практическую ценность отдельно от других прибамбасов (за исключением ОС и самого компьютера) и при этом могло бы быть получено без указателей в какой бы то ни было части программы, включая и те, что решают подзадачи и зовутся подпрограммами.
Что-то у меня фантазия барахлит, ни одной точной формулировки придумать не могу. Ну, допустим, сделать программу для врачей, в которой можно будет онлайн редактировать информацию о пациентах. При этом база данных на каком-нибудь сервере лежать будет.
P.S. еще есть такой факт, что очень много корпоративного софта пишется на яве, в которой указателей нету вообще.
0
15.11.2011, 13:29
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.11.2011, 13:29
Помогаю со студенческими работами здесь

Что за драйвера такие, для чего они и нужны ли они вообще?
Что за драйвера такие, для чего они и нужны ли они вообще? 1 Intel SATA Preinstall driver (For...

С чего начать для понимание PHP
Добрый день, прошу помощи по изучению веб программирования, на днях пришлось начать...

Указатели на указатели: для чего они могут понадобятся?
Изучаю C++, дошёл до указателей на указатели. Там пишут что эта тема не обязательна. Для чего они...

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


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru