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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.94
CatsCanFly
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
28.07.2013, 20:46     Повторный вызов конструктора?! #1
Мой небольшой класс
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;
- Тоже работает. Оператор присваивания для класса не перегружен. Притом что если явным образом еще раз вызвать конструктор от этого объекта, компилятор конечно ругается. Объясните пожалуйста, что здесь вообще тогда происходит? Еще раз вызывается конструктор и создается новый объект, а старый продолжает висеть в памяти и ссылка на него теряется?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.07.2013, 20:46     Повторный вызов конструктора?!
Посмотрите здесь:

вызов конструктора C++
C++ Повторный вызов деструктора
C++ Повторный вызов процедуры
вызов конструктора C++
C++ Повторный вызов конструктора класса
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
28.07.2013, 20:56     Повторный вызов конструктора?! #2
Цитата Сообщение от CatsCanFly Посмотреть сообщение
CString str = "test";
Тут вызывается конструктор с параметром, а затем конструктор копирования, но в целях оптимизации компилятор может выкинуть "лишний" вызов конструктора.

Добавлено через 1 минуту
Цитата Сообщение от CatsCanFly Посмотреть сообщение
C++
1
str = "test2";
у всех классов по умолчанию есть конструтор копирования и оператор присваивания, если вы не определили их явно
alsav22
5282 / 4801 / 442
Регистрация: 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;
...
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
28.07.2013, 21:14     Повторный вызов конструктора?! #4
str = "test2";
вот тут ситуация немного более хитрая. т.к. явно не задан оператор, принимающий массив чаров или указатель на чаров - то это по идее не должно работать. дефолтный оператор равно генерится для случая, когда справа от оператора = тот же тип. но копмилятор пытается справится с этим и находит вариант с неявным преобразованием. у CString есть нужный конструктор. он и вызывается, т.о. создается объект нужного типа и дальше уже работает дефолтный оператор равно. если CString сделать эксплицидным (написать explicit перед ним), то эта фича пропадет.
ну и еще дефолтный оператор = в вашем случае будет приводить к глюкам. нужно явно свой писать.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
28.07.2013, 21:18     Повторный вызов конструктора?! #5
И деструктор.
Dmitriy_M
1294 / 1175 / 104
Регистрация: 20.03.2009
Сообщений: 4,205
Записей в блоге: 11
28.07.2013, 21:22     Повторный вызов конструктора?! #6
Цитата Сообщение от Jupiter Посмотреть сообщение
Тут вызывается конструктор с параметром, а затем конструктор копирования, но в целях оптимизации компилятор может выкинуть "лишний" вызов конструктора.
По стандарту
C++
1
Foo bar="test2";
эквивалентен
C++
1
Foo bar("test2");
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11800 / 6779 / 765
Регистрация: 27.09.2012
Сообщений: 16,829
Записей в блоге: 2
Завершенные тесты: 1
28.07.2013, 21:48     Повторный вызов конструктора?! #7
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
эквивалентен
Разница только в преобразованиях
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
28.07.2013, 21:56     Повторный вызов конструктора?! #8
Dmitriy_M, никаких гарантий эквивалентности нет
Dmitriy_M
1294 / 1175 / 104
Регистрация: 20.03.2009
Сообщений: 4,205
Записей в блоге: 11
28.07.2013, 23:03     Повторный вызов конструктора?! #9
Jupiter, перечитай свой первый пост.
C++
1
2
3
CString str = "test";
str = "test2";
cout<<str;
в первой строке вызывается конструктор, во второй то, что ты сказал.
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
28.07.2013, 23:43     Повторный вызов конструктора?! #10
Dmitriy_M, нет, давай цитату из стандарта
CatsCanFly
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";
То вызывается сначала перегруженный оператор присваивания, а потом снова конструктор копирования!
Так же большая просьба в целом по коду сказать, что у меня сделано еще неправильно/неэффективно (не уверен насчет возвращения по ссылке объектом самого себя у оператора присваивания)
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
29.07.2013, 22:00     Повторный вызов конструктора?! #12
Цитата Сообщение от CatsCanFly Посмотреть сообщение
При таком создании объекта:
C++
1
CString str("test");
или при таком
C++
1
CString str = "test";
В обоих случаях сначала вызывается конструктор с принимаемым аргументом - массив чаров, а затем конструктор копирования!
нет, только во втором случае может конструктор копирования
stragger
38 / 38 / 2
Регистрация: 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.
CatsCanFly
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
29.07.2013, 22:09  [ТС]     Повторный вызов конструктора?! #14
Извиняюсь, дико затупил. Но вопрос о правильности остается в силе)
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
29.07.2013, 22:09     Повторный вызов конструктора?! #15
Цитата Сообщение от Jupiter Посмотреть сообщение
нет, только во втором случае может вызываться конструктор копирования (зависит от компилятора и опций компиляции)
исправлено
VLK
29.07.2013, 22:11
  #16

Не по теме:

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

alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
29.07.2013, 22:16     Повторный вызов конструктора?! #17
Вот это, по-моему, лишнее:
C++
1
 int char_arr_length(char str_arg[])
strlen() делает тоже самое.
CatsCanFly
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.
Что я не так сделал?
stragger
38 / 38 / 2
Регистрация: 05.12.2011
Сообщений: 343
29.07.2013, 22:18     Повторный вызов конструктора?! #19
CatsCanFly, ну, если по коду посмотреть, то мне не нравится, что ты используешь для выделения памяти malloc/free, а не оператор new/delete. Если пишешь на C++ рекомендуется использовать new/delete, да и удобней он, имхо
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.07.2013, 22:23     Повторный вызов конструктора?!
Еще ссылки по теме:

C++ Вызов конструктора
Повторный вызов деструктора для объекта C++
Исключительные ситуации (повторный вызов деструктора) C++

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

Или воспользуйтесь поиском по форуму:
CatsCanFly
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
29.07.2013, 22:23  [ТС]     Повторный вызов конструктора?! #20
Цитата Сообщение от stragger Посмотреть сообщение
CatsCanFly, ну, если по коду посмотреть, то мне не нравится, что ты используешь для выделения памяти malloc/free, а не оператор new/delete. Если пишешь на C++ рекомендуется использовать new/delete, да и удобней он, имхо
Использую для того что бы сделать например конкатенацию строк, если сумма длин при конкатенации получится больше выделенной памяти, использовать realloc. А как это сделать с new?
Yandex
Объявления
29.07.2013, 22:23     Повторный вызов конструктора?!
Ответ Создать тему
Опции темы

Текущее время: 09:29. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru