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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.94
CatsCanFly
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
#1

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

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

Мой небольшой класс
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++
class X { public: X() {a = 10;}; setA(int value) {a = value;}; private: int a; };

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

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

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

Исключительные ситуации (повторный вызов деструктора) - C++
Всем привет ! Подскажите пожалуйста , почему повторно вызываются деструкторы класса A,B,C? #include &lt;stdio.h&gt; #include...

вызов конструктора - C++
Почему при повторном вызове конструктора выбивает ошибку ?Вот здесь ObjX(INUSE); no match for call to `(aClass) (int&amp;)' #include...

Вызов конструктора - C++
void main() { std::string stemporary; int itemporary; float ftemporary; float fftemporary; ECM *pECM; for (int i=0;i&lt;4;i++) ...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт С++
6553 / 3973 / 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
5416 / 4812 / 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
1481 / 1057 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
28.07.2013, 21:14     Повторный вызов конструктора?! #4
str = "test2";
вот тут ситуация немного более хитрая. т.к. явно не задан оператор, принимающий массив чаров или указатель на чаров - то это по идее не должно работать. дефолтный оператор равно генерится для случая, когда справа от оператора = тот же тип. но копмилятор пытается справится с этим и находит вариант с неявным преобразованием. у CString есть нужный конструктор. он и вызывается, т.о. создается объект нужного типа и дальше уже работает дефолтный оператор равно. если CString сделать эксплицидным (написать explicit перед ним), то эта фича пропадет.
ну и еще дефолтный оператор = в вашем случае будет приводить к глюкам. нужно явно свой писать.
alsav22
5416 / 4812 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
28.07.2013, 21:18     Повторный вызов конструктора?! #5
И деструктор.
Dmitriy_M
1340 / 1221 / 112
Регистрация: 20.03.2009
Сообщений: 4,392
Записей в блоге: 11
28.07.2013, 21:22     Повторный вызов конструктора?! #6
Цитата Сообщение от Jupiter Посмотреть сообщение
Тут вызывается конструктор с параметром, а затем конструктор копирования, но в целях оптимизации компилятор может выкинуть "лишний" вызов конструктора.
По стандарту
C++
1
Foo bar="test2";
эквивалентен
C++
1
Foo bar("test2");
Croessmah
Модератор
Эксперт CЭксперт С++
13045 / 7308 / 814
Регистрация: 27.09.2012
Сообщений: 18,041
Записей в блоге: 3
Завершенные тесты: 1
28.07.2013, 21:48     Повторный вызов конструктора?! #7
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
эквивалентен
Разница только в преобразованиях
Jupiter
Каратель
Эксперт С++
6553 / 3973 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
28.07.2013, 21:56     Повторный вызов конструктора?! #8
Dmitriy_M, никаких гарантий эквивалентности нет
Dmitriy_M
1340 / 1221 / 112
Регистрация: 20.03.2009
Сообщений: 4,392
Записей в блоге: 11
28.07.2013, 23:03     Повторный вызов конструктора?! #9
Jupiter, перечитай свой первый пост.
C++
1
2
3
CString str = "test";
str = "test2";
cout<<str;
в первой строке вызывается конструктор, во второй то, что ты сказал.
Jupiter
Каратель
Эксперт С++
6553 / 3973 / 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
Каратель
Эксперт С++
6553 / 3973 / 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
Каратель
Эксперт С++
6553 / 3973 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
29.07.2013, 22:09     Повторный вызов конструктора?! #15
Цитата Сообщение от Jupiter Посмотреть сообщение
нет, только во втором случае может вызываться конструктор копирования (зависит от компилятора и опций компиляции)
исправлено
VLK
29.07.2013, 22:11
  #16

Не по теме:

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

alsav22
5416 / 4812 / 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++
Здарова! Есть допустим класс: class Str { Str(); Str(Str&amp;); Str(char*); };

Вызов конструктора копии - C++
Не вызывается конструктор копии из производного класса #include &lt;iostream&gt; using namespace std; class A { int x; public: ...

Неоднозначный вызов конструктора - C++
class Verylong{ public: Verylong (long x = 0) { enter(x);} Verylong (const Verylong&amp; vrl) : _sign(vrl._sign),...

Вызов конструктора копий - C++
Почему из строк 186-191 вызывается конструктор копий 83-91? #include &quot;stdafx.h&quot; #define DEBUG #define SHOW_INVARIANTS #include...

Вызов копирующего конструктора - C++
Помогите привести примеры для всех случаев.. Копирующий конструктор вызывается в следующих случаях: 1)если объект типа type...


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

Или воспользуйтесь поиском по форуму:
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     Повторный вызов конструктора?!
Ответ Создать тему
Опции темы

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