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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 50, средняя оценка - 4.64
Svid
5 / 5 / 1
Регистрация: 02.03.2011
Сообщений: 40
#1

Понять указатели:) - C++

10.03.2011, 13:35. Просмотров 6794. Ответов 55
Метки нет (Все метки)

Добрый день!
Совсем недавно начал изучать С++, в основном по методичке, выданной в ВУЗе и по нескольким книгам (Страуструп Б., Стефан Дэвис) и плюс то, что нахожу в интернете. Практически, всё это привязано к ряду лабораторных и контрольных, которые необходимо сделать.
Дошел до указателей....О_о. Проблема вот в чем: те практические примеры, которые показывают использование указателей, не отвечают на вопрос - зачем? То есть, все что сделано в этих примерах с помощью указателей, можно сделать и без них, и нельзя сказать, что это будет сложнее. Из-за этого очень трудно понять смысл указателей и они для меня пока что пустая абстракция.
Есть ли какие-нибудь простые практические примеры, показывающие... почему без указателей не обойтись? Например, очень легко практически объяснить суть цикла или там функции.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.03.2011, 13:35
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Понять указатели:) (C++):

Указатели не могу понять - C++
Все вопросы указал в комментариях к коду. Не могу понять почему так #include <iostream> using namespace std; int main() { int...

Не могу понять зачем нужны указатели? - C++
Не как не могу понять зачем нужны указатели. Я знаю что их надо использовать для выделения памяти, но раньше я и без них обходился

Строки (массив char), указатели. Не могу понять логику! Help! - C++
Вообщем проблема в том что выводятся лишние символы в строках.. хотя в них есть признак окончания строк - нулевой байт я новичок в С...

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

Не могу понять, как "живут" файловые указатели - C++
Не могу понять как живут файловые указатели... Есть у меня файл, и пишу в него 100 интов. Указатель ввода сдвигается на 400, так и надо....

Указатели и указатели на указатели, а также типы данных - C++
Недавно начал изучать Си, перешел с Delphi. Много непонятного и пока процесс идет медленно. Накачал литературы, буду изучать) Щас...

55
talis
791 / 543 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
12.03.2011, 13:03 #31
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Feax, для ответа на ваш вопрос нужно объяснить, что такое пространство имён.

Запустите этот пример:

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
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
int main(int argc, char *argv[])
{
    int var = 18;
    
    cout << "main() var = " << var << endl;
    
    
    if( 1 == 1 ) //всегда истинно
    {
        int var = 24;
        
        cout << "   if var = " << var << endl;
    }
    
    cout << "main() var = " << var << endl;
    
    
    
    {
         int var = 36;
         cout << "   another var = " << var << endl;
    }
    
    
    {
         cout << "var = " << var << endl;
    }
    
    cout << "main() var = " << var << endl;
     
        
    system("pause > nul");
    return 0;
}
Обратите внимание, что int var, созданный непосредственно в операторных скобках main() отличается от int var, созданного в операторных скобках if. Так же на строчке 24 и 30 есть отдельно стоящие операторные скобки, которые не привязаны ни к функции, ни к оператору if, while, for, switch и так далее. Созданная в них int var тоже отличается от int var функции main().

Теперь давайте всё назовём своими именами. Часть кода между операторными скобками называется пространством имён. Подумайте над названием, оно вам многое скажет. У функции main() есть своё пространство имён (тело функции), в нём есть вложенные пространства имён - у оператора if и отдельно стоящее на строчках 24 и 30. int var, объявленная внутри пространств имён if и на строчке 24, перекрывает int var функции main(), но не удаляет её. Они существуют только внутри своих пространств имён и уничтожаются при выходе из них. Теперь посмотрите на пространство имён строчки 30. В нём не объявлена своя int var, поэтому берётся int var из родительского пространства имён, если такая существует. Если нет - просматривается пространство имён ещё более высокого уровня, и так, пока мы не дойдём до глобального. Разумеется, это делается на этапе компиляции и никак не влияет на производительность программы.

Теперь на счёт вашего вопроса. Если вы хотите, чтобы объект существовал после выхода из пространства имён, в котором он создан, создавайте его динамически (new (C++) или malloc (C), или аналогичные). То есть на этапе выполнения программы, память выделяется из кучи (heap). Если он вам нужен только внутри этого пространства имён, и не требуется после него, создавайте его как обычно. Вот пример:

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
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
char * text = 0; //В глобальном пространстве имён.
                 //ВСЕГДА инициализируйте указатели нулём.
 
void allocText()
{
     text = new char[ 256 ];
     cout << "> ";
     cin.getline( text, 256 ); //ввести текст
     
     // выделенная память будет существовать и после выхода из allocText().
}
 
void coutText()
{
    if( text == 0 )
       cout << "text does not exist\n"; //в данный момент text не существует
    else
       cout << "text: " << text << endl;
}
 
int main(int argc, char *argv[])
{
    coutText();
    
    allocText();
    
    coutText();
    
    // удалить text
    delete [] text;
    text = 0; // после удаления ВСЕГДА обнуляйте указатель
    cout << "[deleted]\n";
    
    coutText();
        
    system("pause > nul");
    return 0;
}
Здесь память выделяется динамически функцией allocText(). Ей же заполняется чем-то вменяемым. coutText() выводит содержимое этой памяти, находя нужный участок памяти через char * text. Если text = 0 (нулевой указатель), то память ещё (или уже) не выделена. Всем этим функциям буфер доступен при помощи указателя, который находится в родительском пространстве имён (глобальном в данном случае, хотя это и не обязательно). Тут есть по крайней мере три замечания:

1) Всегда удаляйте динамически выделенную память сами, за вас это никто не сделает. Иначе будут утечки памяти. Вспомните патч к вашей любимой игрушке, где сказано "увеличена производительность за счёт исправления множественных утечек памяти", после которого игрушка стала жрать на 300 метров оперативки меньше. Вот это оно.

2) Если вы случайно удалите указатель (например, при выходе из его пространства имён), вы потеряете буфер. Вы уже никогда не узнаете, в каком участке памяти лежит ваша драгоценная информация. Ну и, опять же, сделаете утечку памяти.

3) Если память не выделена, предназначенный для неё указатель ВСЕГДА должен быть равен нулю. Во-первых, так вы всегда сможете сказать, выделили ли вы память под что-то или нет. Во-вторых, в случае ошибки, операционка отстрелит вашу программу (Инструкция по адресу "0x0022ff77" обратилась к памяти по адресу "0x00000000". Память не может быть read. Ну или written. Помните? ). Подобная ошибка происходит, когда вы пытаетесь обратиться к участку памяти, не доступному вашей программе. Если в указателе будет адрес, который доступен вашей программе, вы можете затереть свою собственную память. Нулевой адрес никогда вам доступен не будет.
4
Feax
9 / 9 / 2
Регистрация: 04.03.2010
Сообщений: 40
12.03.2011, 13:24 #32
talis, большое спасибо за разъяснение. Очень понятно объясняешь С пространством имен был знаком до этого, но возможность использования фигурных скобок для создания нового пространства имен, для меня новость. За это отдельное спасибо
Не понятно только, почему в книжках не говорят про эту особенность указателей.Про замечания очень интересно, также как и интересно все, чего не знал раньше
С++ мне с каждым днем все больше нравится, особенно в сравнении с Delphi.
P.S.: думаю тема скоро перерастет из "Понять указатели" в "Понять С++"
0
Temirlan90
132 / 132 / 8
Регистрация: 30.09.2010
Сообщений: 333
12.03.2011, 21:57 #33
1) Всегда удаляйте динамически выделенную память сами, за вас это никто не сделает. Иначе будут утечки памяти. Вспомните патч к вашей любимой игрушке, где сказано "увеличена производительность за счёт исправления множественных утечек памяти", после которого игрушка стала жрать на 300 метров оперативки меньше. Вот это оно.
talis, Типа в памяти будут хранится лишние данные?
0
silent_1991
Эксперт С++
4985 / 3042 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
12.03.2011, 21:59 #34
Temirlan90, типа система не будет знать, что память приложению уже не нужна и что её теперь можно отдать под более актуальные нужды.
1
Temirlan90
132 / 132 / 8
Регистрация: 30.09.2010
Сообщений: 333
12.03.2011, 22:04 #35
И еще вопрос, в Java и C# это вроде делается на автомате? Я про удаления динамической памяти.

Добавлено через 2 минуты
silent_1991, и в Вашем примере вы показали, что в функцию копируются лишние данные?
0
silent_1991
Эксперт С++
4985 / 3042 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
12.03.2011, 22:08 #36
Вряд-ли вы имеете ввиду мой пример, примеры в основном тут показывал tails.
И да, в Яве и шарпе мусор собирается автоматически.
0
Temirlan90
132 / 132 / 8
Регистрация: 30.09.2010
Сообщений: 333
12.03.2011, 22:13 #37
silent_1991, Я про Real_swap и Image_swap это ведь ваш пример =) В этом исходнике как Я понял, там копируются не нужные данные в функции Image_swap?
Яве и шарпе мусор собирается автоматически
Это лучше или хуже? (Простите за глупый вопрос)
0
silent_1991
Эксперт С++
4985 / 3042 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
12.03.2011, 22:16 #38
Нет, там вообще никакой речи об утечке памяти нету. Там просто было показано, как могут быть использованы указатели.

Добавлено через 2 минуты
Цитата Сообщение от Temirlan90 Посмотреть сообщение
Это лучше или хуже?
Ну, с одной стороны лучше, поскольку вы можете систематически забывать очищать память, и утечки станут критическими. А с другой, когда вы делаете это вручную, то осуществляете более строгий и точный контроль за объектами (можете в любое время удалить объект, когда он станет ненужным). Так что у всего есть и плюсы, и минусы.
1
Temirlan90
132 / 132 / 8
Регистрация: 30.09.2010
Сообщений: 333
12.03.2011, 22:18 #39
C
1
2
3
4
5
6
7
8
void image_swap(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
 
    printf("In image swap:  \ta = %d\tb = %d\n", a, b);
}
Нет, там вообще никакой речи об утечке памяти нету. Там просто было показано, как могут быть использованы указатели.
Я не про утечку говорю. Вот в этой функции ведь создаются 2 новые переменные? Которые как Я понял Нам не нужны...
0
silent_1991
Эксперт С++
4985 / 3042 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
12.03.2011, 22:21 #40
С чего вы взяли? Что в этой функции, что в real_swap, создаются три переменные, только в данном случае это переменные типа int (a, b, temp), а в случае real_swap - два указателя на int и одна int (тоже a, b (указатели) и temp).
0
Temirlan90
132 / 132 / 8
Регистрация: 30.09.2010
Сообщений: 333
12.03.2011, 22:28 #41
silent_1991, просто Я не до конца въезжаю в Ваш пример=)
0
silent_1991
Эксперт С++
4985 / 3042 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
12.03.2011, 22:31 #42
Что конкретно не понятно?
0
Temirlan90
132 / 132 / 8
Регистрация: 30.09.2010
Сообщений: 333
12.03.2011, 22:31 #43
Svid, написал
1) В случае использования передачи параметров в виде переменных, аргументам функции присваивается значение передаваемых переменных, тем самым создавая новые переменные, область видимости которых - функция. И меняются значения созданных внутри функции переменных, а значения переменных, передаваемых аргументами никак не изменяется, ибо они лишь однажды передали свои значения для переменных функции.
получается в image_swap точнее её аргументы не возвращаются в main() функцию?
0
silent_1991
Эксперт С++
4985 / 3042 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
12.03.2011, 22:35 #44
Да суть этого примера в том, чтобы показать, что когда в функцию передаются сами переменные, то все изменения, которые в этой функции над её параметрами совершаются, не коснутся фактических параметров, переданных вызывающей функцией в вызываемую, а когда используются указатели, тут уже все изменения отражаются на фактических параметрах, поскольку передаются их адреса. Тут не стояла цель показать нецелесообразность или расточительность в плане ресурсов.
1
Temirlan90
132 / 132 / 8
Регистрация: 30.09.2010
Сообщений: 333
12.03.2011, 22:44 #45
silent_1991, походу Я Вас в конец ДОСТАЛ вопросами, но зато понял что вы хотели сказать тем исходником =)
0
12.03.2011, 22:44
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.03.2011, 22:44
Привет! Вот еще темы с ответами:

Через указатели на указатели посчитать сумму двух чисел и записать в третье - C++
1. Через указатели на указатели посчитать сумму двух чисел и записать в третье. 2. Написать примитивный калькулятор, пользуясь только...

Указатели на указатели с числами. Почему можно присвоить число в 4-ый элемент, если массив из 2 элементов? - C++
Есть массив int **mas; mas=new int*; // выделил место под пять строк, верно ? mas=new int;// выделил для первой строки матрицы два...

Есть три переменные. Используя указатели на указатели, поменять значение максимальной и минимальной переменной - C++
Мой код. #include &lt;iostream&gt; #include &lt;stdlib.h&gt; #include&lt;iomanip&gt; using namespace std; void min_max(int*pa, int*pb,...

Отсортировать массив и вывести на экран (массивы и указатели на указатели) - C++
Даны массивы F-фамилий студентов и S-результаты сессии (5 оценок) , причем s- результат сессии F студента. Отсортировать массив S по...


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

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

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