Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36

Почему создаются новые объекты?

19.02.2011, 01:03. Показов 2480. Ответов 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
class data 
{
    char* str;
public:
    data(): str("Hi")
    {}
    data(char* ch): str(ch)
    {}
    void setData(char* ch)
    {
        str = ch;
    }
    void printData()
    {
        cout << str << endl;
    }
    virtual ~data ()
    {
        cout << "data deleted\n";
    }
    data& operator= (data& v)
    {
        str = v.str;
        return *this;
    }
};
Обратите внимение на перегруженный оператор = . Если я возвращаю ссылку на data (как в коде), то при присваивании одго экземпляра класса другому, деструктор ничего не пише мне в консоль. Если я возвращаю просто data
C++
1
2
3
4
5
    data operator= (data& v)
    {
        str = v.str;
        return *this;
    }
то при присваивании в консоле дает о себе знать деструктор.
Зачем компилятор создет еще один экземпляр класса data что бы просто передать *this ?
Если кто понимает, то объясните пожалуйста.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.02.2011, 01:03
Ответы с готовыми решениями:

Создаются одинаковые объекты
Доброго времени суток. Начал изучать ООП и столкнулся с проблемой. Пишу класс работы с матрицами. Имеется такой конструктор: ...

Классы: Не создаются объекты класса Apple
Includes.h #include &lt;stdlib.h&gt; #include &lt;gl\glut.h&gt; #include &lt;math.h&gt; #include&lt;stdio.h&gt; #include&lt;time.h&gt; #include&lt;stdio.h&gt; ...

Объекты каких потоков автоматически создаются при запуске программы
Здраствуйте, могу конечно немного переврать вопрос, но звучит примерно так: Объекты каких потоков автоматически создаются при запуске...

21
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.02.2011, 01:07
Потому что вы возвращаете не ссылку, а объект типа data. Чтобы вернуть объект, надо его скопировать в точку вызова, а потом удалить (тот, что был в функции). И компилятору пофиг, что это *this и что после выхода из функции он не уничтожится - вы ему сказали возвращать объект - он это и делает.
0
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 09:50  [ТС]
Я не понял.
Какой удаляется объект?

Кстатиб такой код тоже вызывет деструктор 1 раз (при присваивании)
C++
1
2
3
4
5
    data operator= (data& v)
    {
        str = v.str;
        return data(str);
    }
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.02.2011, 10:16
OMGHero, вы для того, чтобы вернуть объект, создаёте временный, а именно data (str). При возврате объекта вызывается конструктор копии, который копирует этот временный объект в точку вызова, чтобы он стал результатом операции присваивания. Но в функции ведь осталась изначальная копия этого объекта, и при выходе из функции все локальные переменные должны быть уничтожены, следовательно, будет вызван деструктор для этого временного объекта, который был создан в функции как data (str).
0
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 10:32  [ТС]
OMGHero, вы для того, чтобы вернуть объект, создаёте временный, а именно data (str). При возврате объекта вызывается конструктор копии, который копирует этот временный объект в точку вызова, чтобы он стал результатом операции присваивания. Но в функции ведь осталась изначальная копия этого объекта, и при выходе из функции все локальные переменные должны быть уничтожены, следовательно, будет вызван деструктор для этого временного объекта, который был создан в функции как data (str).
Да, этот механизм я понял. Функция создает один объект data (str), потом его уничтожает.
Не понятно что тут создается:
C++
1
2
3
4
5
6
 
 data operator= (data& v)
{
        str = v.str;
        return *this;
}
This не уничтожается. В обоих случаях при выполнении присваивания деконструктор вызывается только один раз. В превом случае понятно что саздается/удаляется (data(str)), во втором нет.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
19.02.2011, 10:35
Цитата Сообщение от OMGHero Посмотреть сообщение
Какой удаляется объект?
Временный. Который программа создаст для того, чтобы передать копию *this в
C++
1
2
3
4
5
* * * * data operator= (data& v)
* * * * {
* * * * * * * * str = v.str;
* * * * * * * * return data(str);
* * * * }
Вы же не ссылку возвращаете, и не указатель, а копию данных. Вот и создается копия класса data, которая удаляется после возвращения значения.

Кстати, некорректно работаете со строками. Вот пример, в котором никто никуда лишний раз не удаляется и содержимое класса Data передается по ссылке:
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
#include <cstdio>
#include <cstring>
 
class Data {
 public:
  Data() : string_(NULL) {}
  explicit Data(const char *string) : string_(NULL) {
    SetData(string);
  }
  ~Data() {
    printf("Debug: Calling destructor %d, '%s'.\n", (int)this, string_);
    delete string_;
  }
  void SetData(const char *string) {
    delete string_;
    string_ = strcpy(new char[strlen(string) + 1], string);
  }
  char *GetData() const { return string_; }
  Data &operator=(const Data &other) {
    if (this != &other)
      SetData(other.GetData());
    return *this;
  }
 private:
  char *string_;
};
 
int main(int argc, char *argv[]) {
  Data a("world!"), b("Hello"), c;
  c = a;
  a = b;
  b = c; // Меняем местами a и b;
  printf("%s %s\n", a.GetData(), b.GetData());
  return 0;
}
Цитата Сообщение от OMGHero Посмотреть сообщение
Не понятно что тут создается:
C++
1
2
3
4
5
data operator= (data& v)
{
        str = v.str;
        return *this; // возвращаем по значению, то бишь копию *this
}
Как что? Копия *this, конечно.
0
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 11:00  [ТС]
lemegeton, а почему так копируете строки
C++
1
2
3
4
5
  
void SetData(const char *string) {
    delete string_;
    string_ = strcpy(new char[strlen(string) + 1], string);
 }
почему просто указатель не присвоить?

Вы же не ссылку возвращаете, и не указатель, а копию данных. Вот и создается копия класса data, которая удаляется после возвращения значения.
Тогда получается что в этом случае деструктор должен вызываться 2 раза
C++
1
2
3
4
5
        data operator= (data& v)
        {
                str = v.str;
                return data(str);
        }
один раз чтобы возвратить объект (возвращаем же копию данных). А второй раз - удалить data (str)
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.02.2011, 13:24
В случае
C++
1
2
3
4
5
data operator= (data& v)
{
        str = v.str;
        return *this;
}
будет создан временный объект, копия *this, который будет возвращён и удалён. В случае
C++
1
2
3
4
5
data operator= (data& v)
{
        str = v.str;
        return data (str);
}
вы вручную создаёте временный объект (data (str) - объект без имени), который будет скопирован в точку вызова, а потом удалён.

Добавлено через 3 минуты
Очень хочется получить сообщение 4 раза - пишите так:
C++
1
2
3
4
5
6
data operator= (data& v)
{
    str = v.str;
    data temporary_object(str);
    return temporary_object;
}
Здесь будет вызван деструктор для удаления temporary_object при выходе из функции (ещё до возвращения копии в точку вызова), а потом, после возврата копии будет ещё и вызван деструктор для удаления автоматически созданного временного объекта.
1
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 13:32  [ТС]
Понял )

Добавлено через 7 минут
Цитата Сообщение от silent_1991 Посмотреть сообщение
Очень хочется получить сообщение 4 раза - пишите так:

data operator= (data& v)
{
str = v.str;
data temporary_object(str);
return temporary_object;
}
Здесь будет вызван деструктор для удаления temporary_object при выходе из функции (ещё до возвращения копии в точку вызова), а потом, после возврата копии будет ещё и вызван деструктор для удаления автоматически созданного временного объекта.
Этот код вызывает один раз деструктор. Проверьте.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
19.02.2011, 13:54
Цитата Сообщение от OMGHero Посмотреть сообщение
почему просто указатель не присвоить?
Ну, во-первых, такое присваивание строк deprecated, во-вторых, чтобы иметь копию значения, а не ссылку на него.
C++
1
2
3
4
5
6
  // предположим, есть char  *string, содержащий "123\0";
  char *a = string;
  // варианты выстрелить себе в ногу:
  srting[0] = '\0'; // изменив строку
  delete [] string; // или даже освободив память
  printf("%s\n", a); // ?????????
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.02.2011, 14:01
OMGHero, проверил. Вывод
Code
1
2
3
4
data deleted
data deleted
data deleted
data deleted
Добавлено через 5 минут
Вообще говоря полезно пробежаться по коду трассировщиком и воочию убедиться, что и где вызывается. Мне очень нравится трассировщик у MSVS2010, им и пользуюсь. Только что специально ради вас прогнал код - вызовы деструкторов:
при выходе из функции operator=, до возврата значения,
после возврата значения
при выходе из main (для удаления d1),
при выходе из main (для удаления d2)
В main у меня были созданы только два объекта, чтобы проверить присваивание.
1
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 14:07  [ТС]
странно, у меня только один раз (без учета удаления объектов d1 и d2)
щас буду разбираться
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.02.2011, 14:19
Если интересно, вот код (вдруг вы чего у себя не поменяли или ещё что):
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
#include <iostream>
 
using namespace std;
 
class data 
{
    char* str;
public:
    data(): str("Hi")
    {
    }
 
    data(char* ch): str(ch)
    {
    }
    
    data(const data &original):
    str(original.str)
    {
    }
 
    void setData(char* ch)
    {
        str = ch;
    }
    
    void printData()
    {
        cout << str << endl;
    }
    
    virtual ~data ()
    {
        cout << "data deleted\n";
    }
    
    data operator=(data& v)
    {
        str = v.str;
 
        data temporary_object(str);
 
        return temporary_object;
    }
};
 
int main()
{
    data d1("Hello");
    data d2("World");
 
    d1.printData();
    d2.printData();
 
    d1 = d2;
 
    d1.printData();
    d2.printData();
 
    return 0;
}
Вот вывод:
Code
1
2
3
4
5
6
7
8
Hello
World
data deleted
data deleted
World
World
data deleted
data deleted
Добавлено через 1 минуту
Ещё для наглядности добавил конструктор копии, чтобы при трассировке видеть, когда он вызывается, на работу деструкторов он, естественно, не влияет.
1
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
19.02.2011, 14:26
silent_1991, а я обычно смотрю примерно вот так
код и результат
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
#include <iostream>
 
class sample {
public:
    sample() {
        std::cout << "create of sample object: "    // comment
              << this << std::endl;         // object
    }
 
    sample(const sample& s) {
        std::cout << "create of sample object: "
              << this << std::endl;         // object
    }
 
    sample& operator = (const sample& s) {
        return *this;
    }
 
    ~sample() {
        std::cout << "destroy of sample object: "   // comment
              << this << std::endl;         // object
                  
    }
};
 
int main()
{
    sample a, c;
    sample b = a;
    
    c = b;
 
    return 0;
}
Code
1
2
3
4
5
6
create of sample object: 001BFE8F
create of sample object: 001BFE83
create of sample object: 001BFE77
destroy of sample object: 001BFE77
destroy of sample object: 001BFE83
destroy of sample object: 001BFE8F
. Видно какой объект создался и какой удалился.
2
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.02.2011, 14:32
fasked, не, старый добрый метод принтэфной отладки, конечно, никто не отменял))) Но мне как-то в последнее время удобно пользоваться трассировщиком, тем более что мелкомягкие в этот раз действительно на славу постарались)))
0
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 14:33  [ТС]
silent_1991, не могли бы вы дать ссылку на мануал где этот трассировщик в visual studio. я его до этого никогда не использовал. В гугле Ip трассировщики вылазают
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.02.2011, 14:40
OMGHero, вы просто жмёте F10 или F11 и пошагово прогоняете программу. Внизу появится окно трассировки с отображением значений всех переменных, а маркер будет указывать на строку, которая выполняется. При этом F10 - шаг с обходом (например, пропуск функции, т.е. функция фактически будет вызвана и выполнена, но отображено это не будет и произойдёт переход на следующую строку), а F11 - шаг с заходом - подробная трассировка, будет выполнен заход всюду, куда только можно.
0
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 14:47  [ТС]
Цитата Сообщение от silent_1991 Посмотреть сообщение
вы просто жмёте F10 или F11 и пошагово прогоняете программу. Внизу появится окно трассировки с отображением значений всех переменных, а маркер будет указывать на строку, которая выполняется. При этом F10 - шаг с обходом (например, пропуск функции, т.е. функция фактически будет вызвана и выполнена, но отображено это не будет и произойдёт переход на следующую строку), а F11 - шаг с заходом - подробная трассировка, будет выполнен заход всюду, куда только можно.
а как увидеть какие объекты создаются ? например как увидеть какой объект создается при возврате функцией *this ?
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
19.02.2011, 14:52
OMGHero, ну это ведь временный объект, имени у него нет. Потому он не будет отображаться в списке переменных. Но по-моему и так понятно, что это тот самый временный объект, который возвращается в точку вызова (потому что он удаляется после вызова return, но до выхода из функции).
0
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 15:00  [ТС]
silent_1991, Вот результат вашего кода у меня. Наверное разница в компиляторах, может мой что-то соптимизировал и не стал создавать еще один объект. Пользуюсь Visual Studio 2010

Code
1
2
3
4
5
6
7
Hello
World
data deleted
World
World
data deleted
data deleted
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
19.02.2011, 15:00
Помогаю со студенческими работами здесь

Написать программу, в которой создаются и разрушаются объекты, определенного пользователем класса
Цель: Получить практические навыки реализации классов на С ++. Основное содержание работы Написать программу, в которой создаются и...

Не создаются новые потоки при распараллеливании цикла for (работает только один поток - главный)
Доброго времени суток, ребята! Пишу код по распараллеливанию умножения матриц. Всё вроде работает верно, но есть один момент OMP не...

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

Почему при программировании C++/Win32 создаются элементы старого вида?
И снова всем здравствуйте!!! Я продолжаю грызть гранит программирования на C++ В общем проблема следующая при создании приложения Win32 в...

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru