0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
1

Повторный вызов конструктора?!

28.07.2013, 20:46. Показов 7549. Ответов 39
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Мой небольшой класс
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
class CString
{
private:
    char* str;
    int len;
    int real_size;
public:
    CString() : len(0), real_size(10)
    {
        this->str = (char*)malloc(this->real_size * sizeof(char));
    }
 
    CString(char str_arg[])
    {
        this->len = char_arr_length(str_arg);
        this->real_size = this->len + 10;
        this->str = (char*)malloc(this->len * sizeof(char));
        this->set(str_arg);
    }
 
    CString* set(char str_arg[])
    {
        for(int i = 0; str_arg[i] != 0; i++)
        {
            this->str[i] = str_arg[i];
        }
        str[this->len] = 0;
        return this;
    }
 
private:
    int char_arr_length(char str_arg[])
    {
        int i;
        for(i = 0; str_arg[i] != 0; i++);
        return i;
    }
 
    friend ostream & operator << (ostream & output, CString & _str)
    {
        output << _str.str;
        return output;
    }
};
Как понимаю, одноаргументные конструкторы можно вызывать как будто это присваивание:
C++
1
2
CString str = "test";
cout<<str;
Естественно , все работает, но мое удивление вызвало :
C++
1
2
3
CString str = "test";
str = "test2";
cout<<str;
- Тоже работает. Оператор присваивания для класса не перегружен. Притом что если явным образом еще раз вызвать конструктор от этого объекта, компилятор конечно ругается. Объясните пожалуйста, что здесь вообще тогда происходит? Еще раз вызывается конструктор и создается новый объект, а старый продолжает висеть в памяти и ссылка на него теряется?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.07.2013, 20:46
Ответы с готовыми решениями:

Повторный вызов конструктора класса
class X { public: X() {a = 10;}; setA(int value) {a = value;}; private: ...

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

Функции, повторный вызов
Здравствуйте! Можете помочь? Например есть функция любая например: void showMsg{cout&lt;&lt;&quot;Foo&quot;;}и мне...

Повторный вызов деструктора
{ bar b; b.~bar(); } В данном примере деструктор bar вызовется дважды. Как у уже удаленного...

39
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
28.07.2013, 20:56 2
Цитата Сообщение от CatsCanFly Посмотреть сообщение
CString str = "test";
Тут вызывается конструктор с параметром, а затем конструктор копирования, но в целях оптимизации компилятор может выкинуть "лишний" вызов конструктора.

Добавлено через 1 минуту
Цитата Сообщение от CatsCanFly Посмотреть сообщение
C++
1
str = "test2";
у всех классов по умолчанию есть конструтор копирования и оператор присваивания, если вы не определили их явно
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
28.07.2013, 21:06 3
Тут выход за границу массива:
C++
1
2
3
4
this->str = (char*)malloc(this->len * sizeof(char));
...
str[this->len] = 0;
...
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
28.07.2013, 21:14 4
str = "test2";
вот тут ситуация немного более хитрая. т.к. явно не задан оператор, принимающий массив чаров или указатель на чаров - то это по идее не должно работать. дефолтный оператор равно генерится для случая, когда справа от оператора = тот же тип. но копмилятор пытается справится с этим и находит вариант с неявным преобразованием. у CString есть нужный конструктор. он и вызывается, т.о. создается объект нужного типа и дальше уже работает дефолтный оператор равно. если CString сделать эксплицидным (написать explicit перед ним), то эта фича пропадет.
ну и еще дефолтный оператор = в вашем случае будет приводить к глюкам. нужно явно свой писать.
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
28.07.2013, 21:18 5
И деструктор.
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
28.07.2013, 21:22 6
Цитата Сообщение от Jupiter Посмотреть сообщение
Тут вызывается конструктор с параметром, а затем конструктор копирования, но в целях оптимизации компилятор может выкинуть "лишний" вызов конструктора.
По стандарту
C++
1
Foo bar="test2";
эквивалентен
C++
1
Foo bar("test2");
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
28.07.2013, 21:48 7
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
эквивалентен
Разница только в преобразованиях
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
28.07.2013, 21:56 8
Dmitriy_M, никаких гарантий эквивалентности нет
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
28.07.2013, 23:03 9
Jupiter, перечитай свой первый пост.
C++
1
2
3
CString str = "test";
str = "test2";
cout<<str;
в первой строке вызывается конструктор, во второй то, что ты сказал.
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
28.07.2013, 23:43 10
Dmitriy_M, нет, давай цитату из стандарта
1
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
29.07.2013, 21:56  [ТС] 11
Если можно, продолжу свои вопросы по данной задаче:

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
95
96
97
98
99
100
101
102
103
104
105
106
107
class CString
{
private:
    char* str;
    int len;
    int real_size;
public:
    CString() : len(0), real_size(10)
    {
        this->str = (char*)malloc(this->real_size * sizeof(char));
    }
 
    CString(char str_arg[])
    {
        cout<<"overloaded constuctor arg \n";
        this->len = char_arr_length(str_arg);
        this->real_size = this->len + 10;
        this->str = (char*)malloc(this->real_size * sizeof(char));
        this->set(str_arg);
    }
 
    CString (const CString & x)
    {
        this->len = x.len;
        this->real_size = x.real_size;
        this->str = (char*)malloc(this->real_size * sizeof(char));
        this->set(x.str);
    }
 
 
    CString & set(char* str_arg)
    {
        cout<<"overloaded constuctor copy \n";
        for(int i = 0; str_arg[i] != 0; i++)
        {
            this->str[i] = str_arg[i];
        }
        str[this->len] = 0;
        return *this;
    }
 
    CString & operator=(char* str_arg)
    {
        cout<<"overloaded operator \"=\"\n";
        int new_length = this->char_arr_length(str_arg);
        if (new_length >= this->real_size)
            this->reallocate(new_length + 10);
        this->len = new_length;
        this->set(str_arg);
        return *this;
    }
 
    bool operator == (CString & _str)
    {
        if (this->len != _str.len)
            return false;
        for (int i = 0; i < this->len; i++)
        {
            if (_str.str[i] != this->str[i])
                return false;
        }
        return true;
    }
 
    bool operator != (CString & _str)
    {
        if (this->len != _str.len)
            return true;
        for (int i = 0; i < this->len; i++)
        {
            if (_str.str[i] != this->str[i])
                return true;
        }
        return false;
    }
 
    ~CString()
    {
        free(this->str);
    }
 
    char &operator [] (int addr)
    {
        return this->str[addr];
    }
 
private:
    int char_arr_length(char str_arg[])
    {
        int i;
        for(i = 0; str_arg[i] != 0; i++);
        return i;
    }
 
    void reallocate(int new_length)
    {
        free(this->str);
        this->real_size = new_length;
        this->str = (char*)malloc(this->real_size * sizeof(char));
    }
 
    friend ostream & operator << (ostream & output, CString & _str)
    {
        output << _str.str;
        return output;
    }
};
При таком создании объекта:
C++
1
CString str("test");
или при таком
C++
1
CString str = "test";
В обоих случаях сначала вызывается конструктор с принимаемым аргументом - массив чаров, а затем конструктор копирования! Почему так? Поясните мне пожалуйста.
Далее, если после этого сделать
C++
1
str = "yyy";
То вызывается сначала перегруженный оператор присваивания, а потом снова конструктор копирования!
Так же большая просьба в целом по коду сказать, что у меня сделано еще неправильно/неэффективно (не уверен насчет возвращения по ссылке объектом самого себя у оператора присваивания)
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
29.07.2013, 22:00 12
Цитата Сообщение от CatsCanFly Посмотреть сообщение
При таком создании объекта:
C++
1
CString str("test");
или при таком
C++
1
CString str = "test";
В обоих случаях сначала вызывается конструктор с принимаемым аргументом - массив чаров, а затем конструктор копирования!
нет, только во втором случае может конструктор копирования
0
40 / 40 / 5
Регистрация: 05.12.2011
Сообщений: 343
29.07.2013, 22:00 13
C
1
CString str = "test";
это одно и тоже, что и это
C
1
CString str("test");
Конструктор копирования при этом не вызывается. Может, ты опечатался, сообщение
C
1
cout<<"overloaded constuctor copy \n";
стоит выводить в конструкторе копирования, а не в методе set.
0
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
29.07.2013, 22:09  [ТС] 14
Извиняюсь, дико затупил. Но вопрос о правильности остается в силе)
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
29.07.2013, 22:09 15
Цитата Сообщение от Jupiter Посмотреть сообщение
нет, только во втором случае может вызываться конструктор копирования (зависит от компилятора и опций компиляции)
исправлено
0
VLK
29.07.2013, 22:11
  #16

Не по теме:

CatsCanFly, а от куда взята эта программа

0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
29.07.2013, 22:16 17
Вот это, по-моему, лишнее:
C++
1
 int char_arr_length(char str_arg[])
strlen() делает тоже самое.
0
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
29.07.2013, 22:17  [ТС] 18
Цитата Сообщение от VLK Посмотреть сообщение

Не по теме:

CatsCanFly, а от куда взята эта программа

Сам написал конечно, поэтому и спрашиваю по ней. Нужно реализовать класс наподобие std:string, не используя ни его, ни желательно функции из cstring. Так же вопрос по этому классу еще
C++
1
2
3
    CString str = "test";
    CString str2 = "test2";
    str = str2;
Программа запускается и выполняется, но после завершения выдается:
Windows has triggered a breakpoint in lafore.exe.

This may be due to a corruption of the heap, which indicates a bug in lafore.exe or any of the DLLs it has loaded.
Что я не так сделал?
0
40 / 40 / 5
Регистрация: 05.12.2011
Сообщений: 343
29.07.2013, 22:18 19
CatsCanFly, ну, если по коду посмотреть, то мне не нравится, что ты используешь для выделения памяти malloc/free, а не оператор new/delete. Если пишешь на C++ рекомендуется использовать new/delete, да и удобней он, имхо
0
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
29.07.2013, 22:23  [ТС] 20
Цитата Сообщение от stragger Посмотреть сообщение
CatsCanFly, ну, если по коду посмотреть, то мне не нравится, что ты используешь для выделения памяти malloc/free, а не оператор new/delete. Если пишешь на C++ рекомендуется использовать new/delete, да и удобней он, имхо
Использую для того что бы сделать например конкатенацию строк, если сумма длин при конкатенации получится больше выделенной памяти, использовать realloc. А как это сделать с new?
0
29.07.2013, 22:23
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.07.2013, 22:23
Помогаю со студенческими работами здесь

Повторный вызов процедуры
Всем очень добрый день! А подскажите,пожалуйста,в Си++ процедура может вызываться несколько раз в...

Повторный вызов деструктора для объекта
Здравствуйте! К сожалению, я пока не умею пользоваться отладчиком для анализа работы программ,...

Исключительные ситуации (повторный вызов деструктора)
Всем привет ! Подскажите пожалуйста , почему повторно вызываются деструкторы класса A,B,C? ...

вызов конструктора
Почему при повторном вызове конструктора выбивает ошибку ?Вот здесь ObjX(INUSE); no match for...


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

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

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