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

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

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

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

28.07.2013, 20:46. Просмотров 2226. Ответов 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++):

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

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

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

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

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

вызов конструктора - C++
Здарова! Есть допустим класс: class Str { Str(); Str(Str&amp;); Str(char*); };

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
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
5417 / 4813 / 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
1483 / 1059 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
28.07.2013, 21:14 #4
str = "test2";
вот тут ситуация немного более хитрая. т.к. явно не задан оператор, принимающий массив чаров или указатель на чаров - то это по идее не должно работать. дефолтный оператор равно генерится для случая, когда справа от оператора = тот же тип. но копмилятор пытается справится с этим и находит вариант с неявным преобразованием. у CString есть нужный конструктор. он и вызывается, т.о. создается объект нужного типа и дальше уже работает дефолтный оператор равно. если CString сделать эксплицидным (написать explicit перед ним), то эта фича пропадет.
ну и еще дефолтный оператор = в вашем случае будет приводить к глюкам. нужно явно свой писать.
alsav22
5417 / 4813 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
28.07.2013, 21:18 #5
И деструктор.
Dmitriy_M
1342 / 1223 / 112
Регистрация: 20.03.2009
Сообщений: 4,407
Записей в блоге: 11
28.07.2013, 21:22 #6
Цитата Сообщение от Jupiter Посмотреть сообщение
Тут вызывается конструктор с параметром, а затем конструктор копирования, но в целях оптимизации компилятор может выкинуть "лишний" вызов конструктора.
По стандарту
C++
1
Foo bar="test2";
эквивалентен
C++
1
Foo bar("test2");
Croessmah
Модератор
Эксперт CЭксперт С++
13134 / 7397 / 828
Регистрация: 27.09.2012
Сообщений: 18,227
Записей в блоге: 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
1342 / 1223 / 112
Регистрация: 20.03.2009
Сообщений: 4,407
Записей в блоге: 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 Посмотреть сообщение
нет, только во втором случае может вызываться конструктор копирования (зависит от компилятора и опций компиляции)
исправлено
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.07.2013, 22:09
Привет! Вот еще темы с ответами:

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

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

Вызов конструктора копий - C++
Всех приветствую! Имеется следующий простенький код: #include &lt;iostream&gt; using namespace std; class Object { ...

Вызов конструктора с аргументами - C++
есть класс приложения test_proj в интерфейсе класса в файле test_proj.h создается объект класса Settings. class test_proj { ...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
29.07.2013, 22:09
Ответ Создать тему
Опции темы

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