powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / 2 раза вызывается деструктор
25 сообщений из 37, страница 1 из 2
2 раза вызывается деструктор
    #39632350
semen.s.semen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Коллеги помогите пожалуйста

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
struct test {

    test() {
        printf("created\n");
    }

    ~test() {
        printf("released\n");
    }
};

int main() {
    std::map<std::string, test> *aMap = new std::map<std::string, test>();
    std::string s{"aa"};
    test t{};
    aMap->emplace(s, t);
    aMap->clear();

    printf("finished\n");
}



Есть вот такой код
Результат - вот такая печать

created
released
finished
released

Подскажите как сделать так чтобы деструктор (released) не вызывался 2 раза - это же вроде как некорректно
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632366
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semen, у тебя для каждого экземпляра test деструктор вызывается единожды - для экземпляра в map и для экземпляра на стеке (test t).
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632370
semen.s.semen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как это

я же создаю 1 объект test t{}; и кладу его в мап
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632388
kolobok0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semenКак это

я же создаю 1 объект test t{}; и кладу его в мап

1) создаёшь экземпляр где?
2) глагол "кладу" - расшифруй для себя (можно глняуть отладчиком что происходит, только с заходом в саму мапу)

именно про это те и сказали выше.
(круглый)
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632392
semen.s.semen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
test t{};

Создаю на стеке

aMap->emplace(s, t);

Неужели конструктор копирования вызывается ?
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632429
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semen, а как же?! Если ты явно не указал на отсутствие реализации конструктора копирования, он будет создан по умолчанию с реализацией простого копирования байт-в-байт. И вообще - создавать на стеке экземпляры класса, а потом помещать их в map, созданный в куче - моветон.

Делай так:
Код: plaintext
1.
aMap->emplace(s, new test());
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632455
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я маленько наврал. :) Метод emplace принимает ссылки на rvalue:
Код: plaintext
1.
2.
emplace(_Args&&... __args)
{ return _M_t._M_emplace_unique(std::forward<_Args>(__args)...); }

Поэтому, надо делать что-то типа:
Код: plaintext
1.
aMap->emplace(s, test(<параметры_конструктора>));

В этом случае, на стеке будет создан временный экземпляр класса test, а при передаче в map будет задействован либо конструктор копии, либо конструктор пересылки, в зависимости от того, реализованы ли эти конструкторы для класса. Это то, о чем писалось в другой ветке - RVO/NRVO.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632462
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semenКоллеги помогите пожалуйста

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
struct test {

    test() {
        printf("created\n");
    }

    ~test() {
        printf("released\n");
    }
};

int main() {
    std::map<std::string, test> *aMap = new std::map<std::string, test>();
    std::string s{"aa"};
    test t{};
    aMap->emplace(s, t);
    aMap->clear();

    printf("finished\n");
}



Есть вот такой код
Результат - вот такая печать

created
released
finished
released

Подскажите как сделать так чтобы деструктор (released) не вызывался 2 раза - это же вроде как некорректно

У тебя всё нормально с деструкторами.
У тебя ненормально с конструкторами. Ты не всех их "трассируешь".
У тебя в коде вызывается MOVE-конструктор, который ты не замечаешь, игнорируешь, а потом думаешь (неверно), что деструктор вызывается лишний раз.

http://en.cppreference.com/w/cpp/container/map/emplace
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632463
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.sementest t{};

Создаю на стеке

aMap->emplace(s, t);

Неужели конструктор копирования вызывается ?

Ну да, или он.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632466
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devsemen.s.semen, а как же?! Если ты явно не указал на отсутствие реализации конструктора копирования, он будет создан по умолчанию с реализацией простого копирования байт-в-байт. И вообще - создавать на стеке экземпляры класса, а потом помещать их в map, созданный в куче - моветон.

Делай так:
Код: plaintext
1.
aMap->emplace(s, new test());



Ты хотел написать НЕ ДЕЛАЙ так ?
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632468
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devsemen.s.semen, а как же?! Если ты явно не указал на отсутствие реализации конструктора копирования, он будет создан по умолчанию с реализацией простого копирования байт-в-байт.


Нет, implicit конструкторы копирования ничего не копируют байт-в байт.
Это -- расхожий среди новичков миф о С++.
Дефолтный конструктор копирования вызывает копирование предков, затем почленное копирование всех мемберов.
Никакого копирования байт-в байт не происходит никогда.

авторИ вообще - создавать на стеке экземпляры класса, а потом помещать их в map, созданный в куче - моветон.


Не выдумывай ерунду. Ты не на Java пишешь.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632489
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semen,

А зачем вообще map создавать в куче? Если уж создал, то и подчистить за собой надо.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632493
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv, ненаследованные (собственные) члены конструктор копирования по умолчанию может и обычным копированием сделать через MOVSB, задав в регистрах #SI и #DI источник и приемник соответственно, а в регистре #CX - кол-во байт. Конечно, зависит от конкретной реализации компилятора.

Кстати, обращал внимание, как сейчас компиляторы помещают в стек параметры? Никаких тебе множественных PUSH! :) Сразу грузит в #SP значение с учётом смещения для всех параметров, формируя кадр стека и помещает туда параметры обычным MOV.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632494
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivТы хотел написать НЕ ДЕЛАЙ так ?Я чуть ниже исправился. :)
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632495
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivУ тебя в коде вызывается MOVE-конструктор, который ты не замечаешь, игнорируешь, а потом думаешь (неверно), что деструктор вызывается лишний раз.Конструктор пересылки, в отличие от конструктора копии, не создается по умолчанию - необходима явная реализация.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632528
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semenПодскажите как сделать так чтобы деструктор (released) не вызывался 2 раза - это же вроде как некорректно
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
#include <map>
#include <cstdio>
#include <memory>

struct test {

    test() {
        printf("created\n");
    }

    ~test() {
        printf("released\n");
    }
};

int main() {
    std::map<std::string, std::unique_ptr<test>> aMap;
    std::string s{"aa"};
    std::unique_ptr<test> t{new test()};
    aMap.emplace(s, std::move(t));
    aMap.clear();

    printf("finished\n");
};

Код: plaintext
1.
2.
created
released
finished
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632541
semen.s.semen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AmKadsemen.s.semenПодскажите как сделать так чтобы деструктор (released) не вызывался 2 раза - это же вроде как некорректно
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
#include <map>
#include <cstdio>
#include <memory>

struct test {

    test() {
        printf("created\n");
    }

    ~test() {
        printf("released\n");
    }
};

int main() {
    std::map<std::string, std::unique_ptr<test>> aMap;
    std::string s{"aa"};
    std::unique_ptr<test> t{new test()};
    aMap.emplace(s, std::move(t));
    aMap.clear();

    printf("finished\n");
};

Код: plaintext
1.
2.
created
released
finished


Интересно

А в данном случае std::move(t) не приведет к вызову конструктора и созданию еще одного объекта ?
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632561
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devMasterZiv, ненаследованные (собственные) члены конструктор копирования по умолчанию может и обычным копированием сделать через MOVSB, задав в регистрах #SI и #DI источник и приемник соответственно, а в регистре #CX - кол-во байт. Конечно, зависит от конкретной реализации компилятора.

Кстати, обращал внимание, как сейчас компиляторы помещают в стек параметры? Никаких тебе множественных PUSH! :) Сразу грузит в #SP значение с учётом смещения для всех параметров, формируя кадр стека и помещает туда параметры обычным MOV.

Почему ты выдумываешь всё время?
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632564
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devMasterZivУ тебя в коде вызывается MOVE-конструктор, который ты не замечаешь, игнорируешь, а потом думаешь (неверно), что деструктор вызывается лишний раз.Конструктор пересылки, в отличие от конструктора копии, не создается по умолчанию - необходима явная реализация.

Опять фантазии?
Он В ДАННОМ КОНКРЕТНОМ случае не создаётся, потому что деструктор объявлен.
Да, это я прошляпил. Тогда должен использоваться конструктор копирования (который есть всегда если move не объявишь).
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632565
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev, в этой книжке Эффективный и современный С++. 42 рекомендации по использованию C++11 и C++14 написано как устроен std::move. Он "работает" во время компиляции.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632570
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semenА в данном случае std::move(t) не приведет к вызову конструктора и созданию еще одного объекта ?

std::move вообще ничего не делает.
Как он может создавать объект?
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632574
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Trdb_dev, в этой книжке Эффективный и современный С++. 42 рекомендации по использованию C++11 и C++14 написано как устроен std::move. Он "работает" во время компиляции.

Он просто ссылку преобразует в rvalue-ссылку, если это возможно.
И всё. А далее что-то либо копирует из rvalue-ссылки, либо перемещает. Как может.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632576
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semenА в данном случае std::move(t) не приведет к вызову конструктора и созданию еще одного объекта ?Нет. Происходит передача указателя на уже выделенный участог памяти. После передачи указателя ф-ия main им уже не владеет. Исключительные права передаются map-объекту.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632584
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AmKadsemen.s.semenА в данном случае std::move(t) не приведет к вызову конструктора и созданию еще одного объекта ?Нет. Происходит передача указателя на уже выделенный участог памяти. После передачи указателя ф-ия main им уже не владеет. Исключительные права передаются map-объекту.

И зачем ты туда new всобачил?
Чтобы запутать ещё больше?
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632585
semen.s.semen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivAmKadпропущено...
Нет. Происходит передача указателя на уже выделенный участог памяти. После передачи указателя ф-ия main им уже не владеет. Исключительные права передаются map-объекту.

И зачем ты туда new всобачил?
Чтобы запутать ещё больше?

Уважаемый Мастер Зив

Привидите пожалуйста Ваш корректно работающий вариант кода с использованием std::move
...
Рейтинг: 0 / 0
25 сообщений из 37, страница 1 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / 2 раза вызывается деструктор
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]