Форум программистов, компьютерный форум 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++ Повторный вызов конструктора класса
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
29.07.2013, 22:28     Повторный вызов конструктора?! #21
В учебнике у меня была подобная программа, я ее переписывал \ совершенствовал, вот, может будет интересно:

Кликните здесь для просмотра всего текста
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <iostream> 
 
class str
{
public:
 
~str() // Деструктор, удаляет массив
{
delete[] stroka;
dlina_stroki = 0;
}
 
str() // Конструктор по умолчанию, создает массив нулевой длины
{
stroka = new char[1];
stroka[0] = '\0';
dlina_stroki = 0;
}
 
str(const char *rhs) // конструктор, преобразует массив символов в строчку
{
dlina_stroki = strlen(rhs); // устанавливаем длину массива при помощи оператора strlen
stroka = new char[dlina_stroki +1]; // выделяем память под массив на 1 элемент больше
 
for (int i = 0; i < dlina_stroki; i++)
{ stroka[i] = rhs[i]; } // переводим полученные данные (rhs) в свой массив (stroka)
stroka[dlina_stroki] = '\0'; // вставляем в последний элемент массива пробел 
}
 
str(const str & rhs) // конструктор копировщик, работает по тому же принципу что и конструктор выше, принимает значение в качестве ссылки,если НЕ в качестве ссылки, то будет бесконечная рекурсия!
{
dlina_stroki = rhs.get_dlina_stroki();
stroka = new char[dlina_stroki + 1];
 
for (int i = 0; i < dlina_stroki; i++)
{ stroka[i] = rhs[i]; }
stroka[dlina_stroki] = '\0';
}
 
char operator[] (int rhs) const // данный оператор получает номер элемента массива, а так же проверяет, не выходит ли массив за область видимости
{
if (dlina_stroki < rhs)
{ return stroka[dlina_stroki - 1]; }
else
{ return stroka[rhs]; }
}
 
char & operator[] (int rhs) // данный оператор получает номер элемента массива, а так же проверяет, не выходит ли массив за область видимости
{  
if (dlina_stroki < rhs)
{ return stroka[dlina_stroki - 1]; }
else
{ return stroka[rhs]; }
}
 
str & operator= (const str & rhs) // оператор равно для класса str 
{
if (this == &rhs) // проверяем, не пытаемся ли мы приравнять один и тот же объект т.е. var = var
{ return *this; } // если пытаемся, то просто возвращаем ссылку на него
 
delete[] stroka; // удаляем, то, что есть сейчас
dlina_stroki = rhs.get_dlina_stroki(); // узнаем новую длину строки
stroka = new char[dlina_stroki + 1]; // выделяем память под новый массив
 
for (int i = 0; i < dlina_stroki; i++)
{ stroka[i] = rhs[i];  } // переводим полученные данные (rhs) в свой массив (stroka)
stroka[dlina_stroki] = '\0'; // вставляем в последний элемент массива пробел
return *this; // возвращаем новое значение
}
 
str operator+ (const str & rhs)
{
int temp_dlina_stroki = get_dlina_stroki() + rhs.get_dlina_stroki(); // Узнаем необходимую длину строки для двух объектов
str temp(temp_dlina_stroki + 2); // выделяем память под новый временный объект
int i = 0;
int j = 0;
 
for (i; i < dlina_stroki; i++)
{ temp[i] = stroka[i]; } // переводим первую часть во временный массив
 
temp[i] = ' '; // вставляем между массивами (строчками) пробел
i++;
 
for (j ; j < rhs.get_dlina_stroki(); j++, i++ ) 
{ temp[i] = rhs[j];  } // переводим вторую часть во временный массив
 
temp[temp_dlina_stroki + 1] = '\0'; // вставляем в последний элемент массива пробел
return temp; // возвращаем в качестве результата временны объект
}
 
void operator+= (const str & rhs)
{
int rhs_dlina_stroki = rhs.get_dlina_stroki();
int obsh_dlina_stroki = rhs_dlina_stroki + dlina_stroki;
 
str temp(obsh_dlina_stroki + 1);
 
int i, w;
 
for (i = 0; i < dlina_stroki; i++)
{ temp[i] = stroka[i]; }
 
for (w = 0; w < rhs_dlina_stroki; w++, i++)
{ temp[i] = rhs[i-dlina_stroki]; }
temp[obsh_dlina_stroki] = '\0';
*this = temp;
// данный оператор выполняет следующие - varOne += varTwo - varOne = varOne + varTwo
}
 
char *get_stroka() const { return stroka; } // функция член, возвращает массив
int get_dlina_stroki() const { return dlina_stroki; } // функция член, возвращает длину массива
void show_stroka() const { std::cout << stroka << "\n"; } // функция член, выводит на экран строку
 
private:
str(int rhs)
{
dlina_stroki = rhs;
stroka = new char[dlina_stroki +1];
for (int i = 0; i < dlina_stroki; i++)
{ stroka[i] = '\0'; }
stroka[dlina_stroki] = '\0';
}
 
char *stroka; // массив в котором хранится строка
int dlina_stroki; // длина массива
};
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
stragger
38 / 38 / 2
Регистрация: 05.12.2011
Сообщений: 343
29.07.2013, 22:38     Повторный вызов конструктора?! #22
Цитата Сообщение от CatsCanFly Посмотреть сообщение
Использую для того что бы сделать например конкатенацию строк, если сумма длин при конкатенации получится больше выделенной памяти, использовать realloc. А как это сделать с new?
Создать буффер нужного размера с помощью new, скопировать туда содержимое строк и дальше этот буффер присвоить результируещей строке(предварительно удалив с помощью delete, чтобы утечки не было)

По сути, realloc делает тоже самое.

Добавлено через 4 минуты
CatsCanFly, насчет ошибки.
C
1
str = str2
здесь после этой строки str - это побайтовая копия str2. Указатель char* str; один и тот же.
Когда срабатывает деструктор для str и str2 по этому указателю удаление происходит два раза, на втором разе будет ошибка.

Решение: определить оператор = для строк.
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
29.07.2013, 22:43     Повторный вызов конструктора?! #23
Цитата Сообщение от stragger Посмотреть сообщение
По сути, realloc делает тоже самое.

Не по теме:

Если ему не повезёт и он не сможет довыделить память из излишков или от границы кучи.

CatsCanFly
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
30.07.2013, 00:54  [ТС]     Повторный вызов конструктора?! #24
И снова небольшой вопрос Извиняюсь за назойливость:
вот мой класс на данный момент:
Кликните здесь для просмотра всего текста
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
class CString
{
private:
    char* str;
    int len;
    int real_size;
public:
    CString() : len(0), real_size(0)
    {
 
    }
 
    CString(char str_arg[])
    {
        this->len = strlen(str_arg);
        this->real_size = this->len + 10;
        this->str = new char[this->real_size];
        this->set(str_arg);
    }
 
    CString (const CString & x)
    {
        this->len = x.len;
        this->real_size = x.real_size;
        this->str = new char[this->real_size];
        this->set(x.str);
    }
 
    CString & operator=(char str_arg[])
    {
        this->len = this->strlen(str_arg);
        if (this->len >= this->real_size)
        {
            this->reallocate(this->len + 10);
        }
        this->set(str_arg);
        return *this;
    }
 
    CString & operator =(const CString & x)
    {
        this->len = x.len;
        if (this->len >= this->real_size)
            this->reallocate(this->len + 10);
        this->set(x.str);
        return *this;
    }
 
    CString operator + (const CString & x)
    {
        int new_len = this->len + x.len;
        int new_r_size = this->real_size + x.len;
        char* temp = concat_chars(x.str, x.len);        
        return CString(new_r_size, new_len, temp);
    }
 
    CString operator + (char str_arg[])
    {
        int arg_len = this->strlen(str_arg);
        int new_len = this->len + arg_len;
        int new_r_size = this->real_size + arg_len;
        char* temp = concat_chars(str_arg, arg_len);        
        return CString(new_r_size, new_len, temp);
    }
 
    bool operator == (const 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 != (const 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;
    }
 
    char &operator [] (int addr)
    {
        return this->str[addr];
    }
 
    ~CString()
    {
        delete[] this->str;
    }
 
private:
    CString (int _real_size, int _len, char* _str)
    {
        this->len = _len;
        this->real_size = _real_size;
        this->str = _str;
    }
 
    int strlen(char str_arg[])
    {
        int i;
        for(i = 0; str_arg[i] != 0; i++);
        return i;
    }
 
    void reallocate(int new_length)
    {
        this->real_size = new_length;
        delete[] this->str;
        this->str = new char[this->real_size];
    }
 
    void set(char* str_arg)
    {
        for(int i = 0; str_arg[i] != 0; i++)
        {
            this->str[i] = str_arg[i];
        }
        str[this->len] = 0;
    }
 
    char* concat_chars(char* part2, int len2)
    {
        int new_len = this->len + len2;
        char* temp = new char[this->real_size + len2];
        int pointer;
        for(pointer = 0; pointer < this->len; pointer++)
        {
            temp[pointer] = this->str[pointer];
        }
        for(int i = 0; pointer < new_len; pointer++, i++)
        {
            temp[pointer] = part2[i];
        }
        temp[new_len] = 0;
        return temp;
    }
 
    friend ostream & operator << (ostream & output, CString & _str)
    {
        output << _str.str;
        return output;
    }
};

Если сделать так:
C++
1
2
3
CString str1 = "text";
CString str2 = "other";
CString str3 = str1 + str2;
то создается временный объект внутри кода перегруженного оператора + и возвращается им. Только тут получается, что после присваивания str3 мы временный объект теряем, соответственно указатель на массив char который он в себе содержит, и возможность освободить от него память, то есть получаем утечку памяти. Я прав? Подскажите пожалуйста, как решить такую проблему. VLK в своем решении использовал тот же подход что и я, и как понимаю там проблема эта тоже должна быть.
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
30.07.2013, 11:23     Повторный вызов конструктора?! #25
C++
1
2
str test = "Hello world";
str test("Hello world");
у меня в обоих случая вызывался только один конструктор (насколько я понял проблема в том, что вызывалось несколько)
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
30.07.2013, 11:30     Повторный вызов конструктора?! #26
у меня в обоих случая вызывался только один конструктор
а теперь открываем g++ и компилим с -fno-elide-constructors.
или g++ своевольничает и нарушает стантадарт?

Добавлено через 49 секунд
цитату из стандарта об эквивалентности этих двух строк от Dmitriy_M так и не получили
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
30.07.2013, 11:40     Повторный вызов конструктора?! #27
Я не знаю что за g++, что даст "g++ и компилим с -fno-elide-constructors" ? напишет когда вызывается конструктор?
Fyret
184 / 170 / 13
Регистрация: 30.07.2013
Сообщений: 359
30.07.2013, 12:43     Повторный вызов конструктора?! #28
Недавно разбирался для себя с темой пропущенного копирования. Jupiter прав, текущий стандарт 12.8/32.

C++
1
CString str = "test";
Тот факт, что msvc и gcc (на них я проверял) по умолчанию опускают вызов конструктора копирования, не означает, что они обязаны так делать.
CatsCanFly
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
30.07.2013, 12:44  [ТС]     Повторный вызов конструктора?! #29
А по моему последнему вопросу насчет пропадающего объекта и утечки памяти кто то сможет подсказать?
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
30.07.2013, 12:56     Повторный вызов конструктора?! #30
Цитата Сообщение от CatsCanFly Посмотреть сообщение
Если сделать так:
C++
1
2
3
CString str1 = "text";
CString str2 = "other";
CString str3 = str1 + str2;
то создается временный объект внутри кода перегруженного оператора + и возвращается им. Только тут получается, что после присваивания str3 мы временный объект теряем, соответственно указатель на массив char который он в себе содержит, и возможность освободить от него память, то есть получаем утечку памяти. Я прав?
для этого временного объекта вызывается декструктор
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
30.07.2013, 13:03     Повторный вызов конструктора?! #31
Цитата Сообщение от CatsCanFly Посмотреть сообщение
А по моему последнему вопросу насчет пропадающего объекта и утечки памяти кто то сможет подсказать?
В примере который привел я такого нет, сразу после сложения и присвоения срабатывает деструктор
CatsCanFly
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
30.07.2013, 14:50  [ТС]     Повторный вызов конструктора?! #32
Цитата Сообщение от Jupiter Посмотреть сообщение
для этого временного объекта вызывается декструктор
Я проверил, у меня почему то не вызывается.

Цитата Сообщение от VLK Посмотреть сообщение
В примере который привел я такого нет, сразу после сложения и присвоения срабатывает деструктор
Тогда я немного не понял, можно пояснить?
Ни в str & operator= (const str & rhs) ни в str operator+ (const str & rhs) не увидел удаления объекта
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
30.07.2013, 14:55     Повторный вызов конструктора?! #33
CatsCanFly, выкладывайте код который проверяли и который можно скопировать и проверить
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
30.07.2013, 16:12     Повторный вызов конструктора?! #34
Цитата Сообщение от CatsCanFly Посмотреть сообщение
Тогда я немного не понял, можно пояснить?
Ни в str & operator= (const str & rhs) ни в str operator+ (const str & rhs) не увидел удаления объекта
Ну все правильно, ты когда пишешь
int var = 100;
100 это же не где то там, как я понимаю это временный объект, после присвоения, а наверное после выполнения этой строчки и перехода на новую строчку, данный временны объект будет удален.
Я не знаю точно, я только подозреваю, и я надеюсь профессионалы подтвердят мои догадки.
CatsCanFly
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
31.07.2013, 00:49  [ТС]     Повторный вызов конструктора?! #35
Цитата Сообщение от VLK Посмотреть сообщение
Ну все правильно, ты когда пишешь
int var = 100;
100 это же не где то там, как я понимаю это временный объект, после присвоения, а наверное после выполнения этой строчки и перехода на новую строчку, данный временны объект будет удален.
Я не знаю точно, я только подозреваю, и я надеюсь профессионалы подтвердят мои догадки.
Это же простые типы а не объекты. Я понимаю это выражение так: в сегмент кода записывается константа 100, дальше ее значение копируется в переменную var, которая находится в стеке. В сегменте кода навсегда остается эта константа 100. Разве не так?

Добавлено через 8 часов 30 минут
И снова мой вопрос) Проблему с удалением временного объекта решил создав новый перегруженный конструктор и оператор присваивания. Вот мой класс сейчас:
Кликните здесь для просмотра всего текста
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
class CString
{
private:
    char* str;
    int len;
    int real_size;
public:
    CString() : len(0), real_size(0)
    {
 
    }
 
    CString(char str_arg[])
    {
        this->len = strlen(str_arg);
        this->real_size = this->len + 10;
        this->str = new char[this->real_size];
        this->set(str_arg);
    }
 
    CString (const CString & x)
    {
        this->len = x.len;
        this->real_size = x.real_size;
        this->str = new char[this->real_size];
        this->set(x.str);
    }
 
    CString (const CString* x)
    {
        this->len = x->len;
        this->str = x->str;
        this->real_size = x->real_size;
    }
 
    CString & operator=(char str_arg[])
    {
        this->len = this->strlen(str_arg);
        if (this->len >= this->real_size)
        {
            this->reallocate(this->len + 10);
        }
        this->set(str_arg);
        return *this;
    }
 
    CString & operator =(const CString & x)
    {
        this->len = x.len;
        if (this->len >= this->real_size)
            this->reallocate(this->len + 10);
        this->set(x.str);
        return *this;
    }
 
    CString & operator =(CString* x)
    {
        delete[] this->str;
        this->len = x->len;
        this->str = x->str;
        this->real_size = x->real_size;
        return *this;
    }
 
    CString* operator + (const CString & x)
    {
        int new_len = this->len + x.len;
        int new_r_size = this->real_size + x.len;
        char* temp = concat_chars(x.str, x.len);        
        return new CString(new_r_size, new_len, temp);
    }
 
    CString* operator + (char str_arg[])
    {
        int arg_len = this->strlen(str_arg);
        int new_len = this->len + arg_len;
        int new_r_size = this->real_size + arg_len;
        char* temp = concat_chars(str_arg, arg_len);        
        return new CString(new_r_size, new_len, temp);
    }
 
    bool operator == (const 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 != (const 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;
    }
 
    char &operator [] (int addr)
    {
        return this->str[addr];
    }
 
    ~CString()
    {
        delete[] this->str;
    }
 
private:
    CString (int _real_size, int _len, char* _str)
    {
        this->len = _len;
        this->real_size = _real_size;
        this->str = _str;
    }
 
    int strlen(char str_arg[])
    {
        int i;
        for(i = 0; str_arg[i] != 0; i++);
        return i;
    }
 
    void reallocate(int new_length)
    {
        this->real_size = new_length;
        delete[] this->str;
        this->str = new char[this->real_size];
    }
 
    void set(char* str_arg)
    {
        for(int i = 0; str_arg[i] != 0; i++)
        {
            this->str[i] = str_arg[i];
        }
        str[this->len] = 0;
    }
 
    char* concat_chars(char* part2, int len2)
    {
        int new_len = this->len + len2;
        char* temp = new char[this->real_size + len2];
        int pointer;
        for(pointer = 0; pointer < this->len; pointer++)
        {
            temp[pointer] = this->str[pointer];
        }
        for(int i = 0; pointer < new_len; pointer++, i++)
        {
            temp[pointer] = part2[i];
        }
        temp[new_len] = 0;
        return temp;
    }
 
    friend ostream & operator << (ostream & output, CString & _str)
    {
        output << _str.str;
        return output;
    }
};

Но теперь происходит вообще непонятно что:
C++
1
2
3
CString str = "test";
CString str2 = "test2";
CString str3 = str + str2;
- Все работает правильно, но:
C++
1
2
3
CString str = "test";
CString str2 = "test2";
CString str3 = str + str2 + "ttt";
Компилятор выдает:
Error 2 error C2110: '+' : cannot add two pointers
А если сделать
C++
1
CString str3 = str + str2 + str;
то происходят еще более странные вещи:
Error 6 error C2677: binary '+' : no global operator found which takes type 'CString' (or there is no acceptable conversion)
Error 5 error C2784: 'std::_Revranit<_RanIt,_Base> std::operator +(_Diff,const std::_Revranit<_RanIt,_Base> &)' : could not deduce template argument for 'const std::_Revranit<_RanIt,_Base> &' from 'CString'
Error 3 error C2784: 'std::_String_const_iterator<_Elem,_Traits,_Alloc> std::operator +(_String_const_iterator<_Elem,_Traits,_Alloc>::difference_type,std::_String_const_iterator<_Elem,_Traits,_Alloc>)' : could not deduce template argument for 'std::_String_const_iterator<_Elem,_Traits,_Alloc>' from 'CString'
Error 2 error C2784: 'std::_String_iterator<_Elem,_Traits,_Alloc> std::operator +(_String_iterator<_Elem,_Traits,_Alloc>::difference_type,std::_String_iterator<_Elem,_Traits,_Alloc>)' : could not deduce template argument for 'std::_String_iterator<_Elem,_Traits,_Alloc>' from 'CString'
Error 4 error C2784: 'std::reverse_iterator<_RanIt> std::operator +(_Diff,const std::reverse_iterator<_RanIt> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'CString'
Помогите разобраться
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
31.07.2013, 01:06     Повторный вызов конструктора?! #36
Первое сложение возвращает указатель, а не объект, поэтому приходится так:
C++
1
2
CString str3 = *(str + str2) + "ttt"; 
CString str3 = *(str + str2) + str;
CatsCanFly
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
31.07.2013, 01:13  [ТС]     Повторный вызов конструктора?! #37
Цитата Сообщение от alsav22 Посмотреть сообщение
Первое сложение возвращает указатель, а не объект, поэтому приходится так:
C++
1
2
CString str3 = *(str + str2) + "ttt"; 
CString str3 = *(str + str2) + str;
Кажется я понял...а как же это обходит std:string?
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
31.07.2013, 01:23     Повторный вызов конструктора?! #38
Цитата Сообщение от CatsCanFly Посмотреть сообщение
а как же это обходит std:string?
Наверное, там не указатель возвращается.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CString& operator + (const CString & x)
    {
        int new_len = this->len + x.len;
        int new_r_size = this->real_size + x.len;
        char* temp = concat_chars(x.str, x.len);        
        
        return *(new CString(new_r_size, new_len, temp));
    }
 
    CString& operator + (char str_arg[])
    {
        int arg_len = this->strlen(str_arg);
        int new_len = this->len + arg_len;
        int new_r_size = this->real_size + arg_len;
        char* temp = concat_chars(str_arg, arg_len);        
        return *(new CString(new_r_size, new_len, temp));
    }
CatsCanFly
0 / 0 / 0
Регистрация: 14.04.2013
Сообщений: 21
31.07.2013, 01:44  [ТС]     Повторный вызов конструктора?! #39
alsav22, но тогда же я не смогу знать, удалять мне его или нет -
C++
1
2
3
4
5
6
7
8
CString & operator = (const CString & x)
    {
        this->len = x.len;
        if (this->len >= this->real_size)
            this->reallocate(this->len + 10);
        this->set(x.str);
        return *this;
    }
- если этот оператор принимает существующий объект, например str = str2; то удалять str2 он не должен. Как он отличит его от временного объекта, который он должен удалить?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.07.2013, 02:23     Повторный вызов конструктора?!
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
31.07.2013, 02:23     Повторный вызов конструктора?! #40
Понятия не имею, это же ваш класс, а не мой. Думайте.

Добавлено через 6 минут
Если так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CString operator + (const CString & x)
{
        int new_len = this->len + x.len;
        int new_r_size = this->real_size + x.len;
        char* temp = concat_chars(x.str, x.len);        
        
        return CString(new_r_size, new_len, temp);
}
 
CString operator + (char str_arg[])
{
        int arg_len = this->strlen(str_arg);
        int new_len = this->len + arg_len;
        int new_r_size = this->real_size + arg_len;
        char* temp = concat_chars(str_arg, arg_len);        
        return CString(new_r_size, new_len, temp);
}
Yandex
Объявления
31.07.2013, 02:23     Повторный вызов конструктора?!
Ответ Создать тему
Опции темы

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