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

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

Восстановить пароль Регистрация
Другие темы раздела
C++ Распечатать введенную строку, удалив из неё слова с нечетными номерами и добавив перевернутое слово к слову с четными номерами. http://www.cyberforum.ru/cpp-beginners/thread254809.html
Распечатать введенную строку, удалив из неё слова с нечетными номерами и добавив перевернутое слово к слову с четными номерами. Например, из строки: "во что бы то ни стало" Должно получиться: "чтоотч тоот сталоолатс" на паскале она у меня есть, на с не могу написать по аналогии, т.к. на паскале юзал pos delete insert... прошу помогите кто как может. (((((((
C++ Представить число в виде многочлена Дано натуральное число А. Надо составить программу (С++), которая представляет его в виде многочлена. Например, 123 ==> 1 * 10 ^ 2 + 2 * 10 ^ 1 + 3 * 10 ^ 0. /*fizmat goroda Kamenets-Podolsky - RESPECT*/ http://www.cyberforum.ru/cpp-beginners/thread254798.html
C++ Указатели на структуры!
Захватить память для массива из 10 структур. Заполните массив данными из файла "1.dat". Вывести информацию о маршрутах, имеющих определенный пункт в качестве начального или конечного. Высчитать для них среднюю длину. Перед завершением программы освободить память. #include "iostream" #include "stdio.h" using namespace std; struct MARSH { char start_name;
C++ Вычислить период последовательности
Подскажите, как вычислить период последовательности. Как я понимаю, поместить сперва элементы в массив, и уже в нем считать период? ... long t, k, p, a, c, n=20; // p - Xo, t, k - Xn, int i, g, m=8; // m - кол-во элементов, которое надо найти printf ("Vvedite Xo, A, C \n"); scanf ("%d", &p); scanf ("%d", &a); scanf ("%d", &c);
C++ Определите класс «Студент» http://www.cyberforum.ru/cpp-beginners/thread254763.html
Помогите пожалуйста с задачей Определите класс «Студент».Методы – перевод на следующий курс, выпуск, отчисление. Разработать дружественную классу «Студент» функцию, определяющую знак зодиака, под которой студент родился.
C++ решить функцию Всем привет! помогите пожалуйста решить задачки на Borland C Буду крайне признательна! Заранее спасибо! подробнее

Показать сообщение отдельно
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
12.03.2011, 13:03     Понять указатели:)
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. Помните? ). Подобная ошибка происходит, когда вы пытаетесь обратиться к участку памяти, не доступному вашей программе. Если в указателе будет адрес, который доступен вашей программе, вы можете затереть свою собственную память. Нулевой адрес никогда вам доступен не будет.
 
Текущее время: 01:04. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru