Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
438 / 96 / 41
Регистрация: 04.10.2011
Сообщений: 345
1

Инициализация укзателей в классе

30.09.2012, 17:51. Показов 1153. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет читаю книгу Пабло Халперна "Стандарная библиотека С++ на примерах". Там, в качестве обучения читателю предлагается пройти процесс разработки и реализации некоего приложения - записной книжки с использованием STL. Вопрос касается инициализации указателей на массивы строк, и удаление их.
В общем, есть некий класс, автор его реализовал примерно так (это предварительная версия - дальше автор реализует этот класс с использованием типа std::string - кабы люди, не читавшие данной книги не подумали чего нехорошего про автора ):
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
class Address
{
    public:
        Address::Address()
        : lastname_     (new char[1])
        , firstname_    (new char[1])
        , phone_        (new char[1])
        , address_      (new char[1])
        {
            this->lastname_[0]  = '\0'; 
            this->firstname_[0] = '\0'; 
            this->phone_[0]     = '\0';
            this->address_[0]   = '\0';
        }
        ~Address()
        {
            delete [] this->firstname_;
            delete [] this->lastname_;
            delete [] this->phone_;
            delete [] this->address_;
        }
        
        //  . . . Много другого кода . . .
        
    private:
        char *lastname_;
        char *firstname_;
        char *phone_;
        char *address_;
};
А я (только изучаю С++), не подглядывая в реализацию в книжке, но представляя, что нужно сделать, реализовал его вот так:
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
class Address
{
    public:
        Address()
        : lastname_ (NULL)
        , firstname_(NULL)
        , phone_    (NULL)
        , address   (NULL)
        {
            /* пусто */
        }
        ~Address()
        {
            delete this->firstname_;
            delete this->lastname_;
            delete this->phone_;
            delete this->address_;
        }
        
        //  . . . Много другого кода . . .
        
    private:
        char *lastname_;
        char *firstname_;
        char *phone_;
        char *address_;
};
Вопрос в том, правильно ли я работаю с указателями? - Подозреваю, что нет. И какие ошибки я допускаю в данном случае?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.09.2012, 17:51
Ответы с готовыми решениями:

Инициализация массива в классе
Как инициализировать массив в классе? Пишу такой код, но компилятор выдает: 9:53: error:...

Инициализация char в классе
Не понимаю, как поместить символьный массив в класс. На выводе получаются случайные символы. class...

Инициализация массива в классе
class matrix { int arr; ...... public: .............. void set_a(int input, int i, int...

Инициализация переменной в классе
Пытаюсь инициализировать в классе переменную и дальше ее использовать class Lines { double PI =...

6
873 / 771 / 173
Регистрация: 11.01.2012
Сообщений: 1,942
30.09.2012, 18:13 2
А нет вообще то ошибки не будет все корректно
1
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
30.09.2012, 18:25 3
не совсем так.
по стандарту, оператор delete ничего не делает с нулевыми указателями. поэтому, если указатель инициализировать нулем (а ТС это сделал), то все корректно отработает.
C++
1
2
char* p = 0;
delete p; // ok
писать this пожалуй лишнее. редко встречал код-стайлы, где требовали это делать.
ну и еще если первый листинг из книжки - то сам автор демонстрирует написание кода, небезопасного с точки зрения исключений. в нем возможны утечки.
в списке инициализации больше одного new для инициализации голых указателей писать не стоит.
1
873 / 771 / 173
Регистрация: 11.01.2012
Сообщений: 1,942
30.09.2012, 18:26 4
Если указатели обнулили то при вызове оператора delete
ошибки не будет
1
438 / 96 / 41
Регистрация: 04.10.2011
Сообщений: 345
30.09.2012, 18:42  [ТС] 5
Цитата Сообщение от MrCold Посмотреть сообщение
Если указатели обнулили то при вызове оператора delete
ошибки не будет
А... как бы во время работы указатели конечно же будут указывать на какие то данные, приведу полный листинг класса (как у автора, у меня получилось всё тоже самое, но разница была в том, что показывают листинги в начале топика). Класс просто является контейнером, который имеет 4 текстовых поля и методы для установки и получения значений + перегруженные оператор и конструктор копирования, .
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
94
class Address
{
    public: 
        Address()
        : lastname_     (new char[1])
        , firstname_    (new char[1])
        , phone_        (new char[1])
        , address_      (new char[1])
        {
            this->lastname_[0]  = '\0';
            this->firstname_[0] = '\0';
            this->phone_[0]     = '\0'; 
            this->address_[0]   = '\0';
        }       
        ~Address()
        {
            delete [] this->firstname_;
            delete [] this->lastname_;
            delete [] this->phone_;
            delete [] this->address_;
        }       
        Address(const Address &a)
        : lastname_     (0)
        , firstname_    (0)
        , phone_        (0)
        , address_      (0)
        {
            *this = a;
        }       
        const Address& operator = (const Address &a)
        {
            if (this != &a) {
                this->lastname(a.lastname());
                this->firstname(a.firstname());
                this->phone(a.phone());
                this->address(a.address());
            }
            return *this;
        }
        
        // Чтение lastname
        const char* lastname() const {return this->lastname_;}
        // Запись lastname
        void lastname(const char* s)
        {
            if (this->lastname_ == s) return;
            delete [] this->lastname_;
            this->lastname_ = this->dup(s);
        }
        
        // Чтение firstname
        const char* firstname() const {return this->firstname_;}
        // Запись firstname
        void firstname(const char* s)
        {
            if (this->firstname_ == s) return;
            delete [] this->firstname_;
            this->firstname_ = this->dup(s);
        }
        
        // Чтение phone
        const char* phone() const {return this->phone_;}
        // Запись phone
        void phone(const char* s)
        {
            if (this->phone_ == s) return;
            delete [] this->phone_;
            this->phone_ = this->dup(s);
        }
        
        // Чтение address
        const char* address() const {return this->address_;}
        // Запись address
        void address(const char* s)
        {
            if (this->address_ == s) return;
            delete [] this->address_;
            this->address_ = this->dup(s);
        }
        
    private:
        char *lastname_;
        char *firstname_;
        char *phone_;
        char *address_;
        
        // Глубинное копирование данных указателя:
        char* dup(const char *s)
        {
            char *newstr = new char [std::strlen(s) + 1];
            std::strcpy(newstr, s);
            return newstr;
        }
};
Вот как у меня:
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
class Address
{
    public: 
        Address()
        : lastname_     (NULL)
        , firstname_    (NULL)
        , phone_        (NULL)
        , address_      (NULL)
        { }       
        ~Address()
        {
            delete this->firstname_;
            delete this->lastname_;
            delete this->phone_;
            delete this->address_;
        }       
        Address(const Address &a)
        : lastname_     (NULL)
        , firstname_    (NULL)
        , phone_        (NULL)
        , address_      (NULL)
        {
            *this = a;
        }       
        const Address& operator = (const Address &a)
        {
            if (this != &a) {
                this->lastname(a.lastname());
                this->firstname(a.firstname());
                this->phone(a.phone());
                this->address(a.address());
            }
            return *this;
        }
        
        // Чтение lastname
        const char* lastname() const {return this->lastname_;}
        // Запись lastname
        void lastname(const char* s)
        {
            if (this->lastname_ == s) return;
            delete this->lastname_;
            this->lastname_ = this->dup(s);
        }
        
        // Чтение firstname
        const char* firstname() const {return this->firstname_;}
        // Запись firstname
        void firstname(const char* s)
        {
            if (this->firstname_ == s) return;
            delete this->firstname_;
            this->firstname_ = this->dup(s);
        }
        
        // Чтение phone
        const char* phone() const {return this->phone_;}
        // Запись phone
        void phone(const char* s)
        {
            if (this->phone_ == s) return;
            delete this->phone_;
            this->phone_ = this->dup(s);
        }
        
        // Чтение address
        const char* address() const {return this->address_;}
        // Запись address
        void address(const char* s)
        {
            if (this->address_ == s) return;
            delete this->address_;
            this->address_ = this->dup(s);
        }
        
    private:
        char *lastname_;
        char *firstname_;
        char *phone_;
        char *address_;
        
        // Глубинное копирование данных указателя:
        char* dup(const char *s)
        {
            char *newstr = new char [std::strlen(s) + 1];
            std::strcpy(newstr, s);
            return newstr;
        }
};
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
30.09.2012, 18:51 6
ну разница есть.
всякие функции работы со строками обычно не ожидают что им нуль подсунут. у автора книги этого не случится. потому что всегда под строки выделяется массив и записывается нолик. тем самым строка есть, но она нулевой длинны. у вас же не так. если попробовать взять какую-то строку, которую неинициализировали, то функция вернет нулевой указатель. это может быть проблемой, а может и нет. но удобнее все-таки, когда гарантируется возврат ненулевого указателя.

неплохо бы еще от копипаста избавится. в коде куча функций с одинаковым кодом:
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
 if (this->address_ == s)
  return;
 delete this->address_;
 this->address_ = this->dup(s);
 
 
можно было бы заменить на одну функцию:
void clone(const char* src, char*& target)
{
 if (src == target)
  return;
 delete target;
 target = dup(s);
}
 
 
и тогда все функции установки новой строки превращаются в однострочные:
void phone(const char* s)
{
  clone(s, phone_);
}
        
void address(const char* s)
{
  clone(s, target_);
}
0
438 / 96 / 41
Регистрация: 04.10.2011
Сообщений: 345
30.09.2012, 19:05  [ТС] 7
Цитата Сообщение от DU Посмотреть сообщение
неплохо бы еще от копипаста избавится. в коде куча функций с одинаковым кодом
- Да - да. Автор книги обращает внимание на этот момент Всем спасибо.
0
30.09.2012, 19:05
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.09.2012, 19:05
Помогаю со студенческими работами здесь

Инициализация valarray в классе
Добрый день. Требуется помощь коллективного разума: совсем забыл, как прогать. Есть следующий...

Инициализация массива в классе
OS: WinXP Compiler: VC++ 6.0 Извиняюсь, заранее за глупый вопрос, но тем не менее: Есть...

Инициализация указателя в классе
Есть класс const int NoL = 0; class A{ private: int& IF; A(){IF = NoL; }; } на что...

Инициализация статической константы в классе
собственно сабж как это сделать если константа имеет тип класса? (не интегральная) т.е. надо...


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

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