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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.70
OMGHero
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 01:03     Почему создаются новые объекты? #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
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 ?
Если кто понимает, то объясните пожалуйста.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.02.2011, 01:03     Почему создаются новые объекты?
Посмотрите здесь:

C++ как создаются 3д игры на с++?
имеется список указателей на авторские объекты, чё-то я могу воспользоваться только первым его элементом! Почему? C++
C++ Контролы создаются, но пропадают.
C++ В окне перемещаются объекты, отталкиваясь от стенок окна. Каждый объект имеет свой поток, перемещающий его. Встретившись, объекты начинают двигаться
Как на си++ создаются приложения с GUI? C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.02.2011, 01:07     Почему создаются новые объекты? #2
Потому что вы возвращаете не ссылку, а объект типа data. Чтобы вернуть объект, надо его скопировать в точку вызова, а потом удалить (тот, что был в функции). И компилятору пофиг, что это *this и что после выхода из функции он не уничтожится - вы ему сказали возвращать объект - он это и делает.
OMGHero
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 09:50  [ТС]     Почему создаются новые объекты? #3
Я не понял.
Какой удаляется объект?

Кстатиб такой код тоже вызывет деструктор 1 раз (при присваивании)
C++
1
2
3
4
5
    data operator= (data& v)
    {
        str = v.str;
        return data(str);
    }
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.02.2011, 10:16     Почему создаются новые объекты? #4
OMGHero, вы для того, чтобы вернуть объект, создаёте временный, а именно data (str). При возврате объекта вызывается конструктор копии, который копирует этот временный объект в точку вызова, чтобы он стал результатом операции присваивания. Но в функции ведь осталась изначальная копия этого объекта, и при выходе из функции все локальные переменные должны быть уничтожены, следовательно, будет вызван деструктор для этого временного объекта, который был создан в функции как data (str).
OMGHero
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 10:32  [ТС]     Почему создаются новые объекты? #5
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)), во втором нет.
lemegeton
 Аватар для lemegeton
2909 / 1338 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
19.02.2011, 10:35     Почему создаются новые объекты? #6
Цитата Сообщение от 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, конечно.
OMGHero
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 11:00  [ТС]     Почему создаются новые объекты? #7
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)
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.02.2011, 13:24     Почему создаются новые объекты? #8
В случае
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 при выходе из функции (ещё до возвращения копии в точку вызова), а потом, после возврата копии будет ещё и вызван деструктор для удаления автоматически созданного временного объекта.
OMGHero
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 13:32  [ТС]     Почему создаются новые объекты? #9
Понял )

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

data operator= (data& v)
{
str = v.str;
data temporary_object(str);
return temporary_object;
}
Здесь будет вызван деструктор для удаления temporary_object при выходе из функции (ещё до возвращения копии в точку вызова), а потом, после возврата копии будет ещё и вызван деструктор для удаления автоматически созданного временного объекта.
Этот код вызывает один раз деструктор. Проверьте.
lemegeton
 Аватар для lemegeton
2909 / 1338 / 133
Регистрация: 29.11.2010
Сообщений: 2,720
19.02.2011, 13:54     Почему создаются новые объекты? #10
Цитата Сообщение от 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); // ?????????
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.02.2011, 14:01     Почему создаются новые объекты? #11
OMGHero, проверил. Вывод
Код
data deleted
data deleted
data deleted
data deleted
Добавлено через 5 минут
Вообще говоря полезно пробежаться по коду трассировщиком и воочию убедиться, что и где вызывается. Мне очень нравится трассировщик у MSVS2010, им и пользуюсь. Только что специально ради вас прогнал код - вызовы деструкторов:
при выходе из функции operator=, до возврата значения,
после возврата значения
при выходе из main (для удаления d1),
при выходе из main (для удаления d2)
В main у меня были созданы только два объекта, чтобы проверить присваивание.
OMGHero
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 14:07  [ТС]     Почему создаются новые объекты? #12
странно, у меня только один раз (без учета удаления объектов d1 и d2)
щас буду разбираться
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.02.2011, 14:19     Почему создаются новые объекты? #13
Если интересно, вот код (вдруг вы чего у себя не поменяли или ещё что):
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;
}
Вот вывод:
Код
Hello
World
data deleted
data deleted
World
World
data deleted
data deleted
Добавлено через 1 минуту
Ещё для наглядности добавил конструктор копии, чтобы при трассировке видеть, когда он вызывается, на работу деструкторов он, естественно, не влияет.
fasked
Эксперт C++
 Аватар для fasked
4924 / 2504 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
19.02.2011, 14:26     Почему создаются новые объекты? #14
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;
}
Код
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
. Видно какой объект создался и какой удалился.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.02.2011, 14:32     Почему создаются новые объекты? #15
fasked, не, старый добрый метод принтэфной отладки, конечно, никто не отменял))) Но мне как-то в последнее время удобно пользоваться трассировщиком, тем более что мелкомягкие в этот раз действительно на славу постарались)))
OMGHero
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 14:33  [ТС]     Почему создаются новые объекты? #16
silent_1991, не могли бы вы дать ссылку на мануал где этот трассировщик в visual studio. я его до этого никогда не использовал. В гугле Ip трассировщики вылазают
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.02.2011, 14:40     Почему создаются новые объекты? #17
OMGHero, вы просто жмёте F10 или F11 и пошагово прогоняете программу. Внизу появится окно трассировки с отображением значений всех переменных, а маркер будет указывать на строку, которая выполняется. При этом F10 - шаг с обходом (например, пропуск функции, т.е. функция фактически будет вызвана и выполнена, но отображено это не будет и произойдёт переход на следующую строку), а F11 - шаг с заходом - подробная трассировка, будет выполнен заход всюду, куда только можно.
OMGHero
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 14:47  [ТС]     Почему создаются новые объекты? #18
Цитата Сообщение от silent_1991 Посмотреть сообщение
вы просто жмёте F10 или F11 и пошагово прогоняете программу. Внизу появится окно трассировки с отображением значений всех переменных, а маркер будет указывать на строку, которая выполняется. При этом F10 - шаг с обходом (например, пропуск функции, т.е. функция фактически будет вызвана и выполнена, но отображено это не будет и произойдёт переход на следующую строку), а F11 - шаг с заходом - подробная трассировка, будет выполнен заход всюду, куда только можно.
а как увидеть какие объекты создаются ? например как увидеть какой объект создается при возврате функцией *this ?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.02.2011, 14:52     Почему создаются новые объекты? #19
OMGHero, ну это ведь временный объект, имени у него нет. Потому он не будет отображаться в списке переменных. Но по-моему и так понятно, что это тот самый временный объект, который возвращается в точку вызова (потому что он удаляется после вызова return, но до выхода из функции).
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.02.2011, 15:00     Почему создаются новые объекты?
Еще ссылки по теме:

Функция создает объекты и указателями на них заполняет массив. При выходе из функции вызываются деструкторы объектов. Как сохранить объекты? C++
Классы: Не создаются объекты класса Apple C++
C++ OpenMP, не создаются потоки

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

Или воспользуйтесь поиском по форуму:
OMGHero
2 / 2 / 0
Регистрация: 16.02.2011
Сообщений: 36
19.02.2011, 15:00  [ТС]     Почему создаются новые объекты? #20
silent_1991, Вот результат вашего кода у меня. Наверное разница в компиляторах, может мой что-то соптимизировал и не стал создавать еще один объект. Пользуюсь Visual Studio 2010

Код
Hello
World
data deleted
World
World
data deleted
data deleted
Yandex
Объявления
19.02.2011, 15:00     Почему создаются новые объекты?
Ответ Создать тему
Опции темы

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