powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / 2 раза вызывается деструктор
12 сообщений из 37, страница 2 из 2
2 раза вызывается деструктор
    #39632588
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivDima Trdb_dev, в этой книжке Эффективный и современный С++. 42 рекомендации по использованию C++11 и C++14 написано как устроен std::move. Он "работает" во время компиляции.

Он просто ссылку преобразует в rvalue-ссылку, если это возможно.Мне больше нравится, как сказано у самого Мейерса: std::move преобразует в rvalue (без "-ссылку").
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632593
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
semen.s.semenПривидите пожалуйста Ваш корректно работающий вариант кода с использованием std::move
ИМХО лучше почитай об этом в книге Эффективный и современный С++. 42 рекомендации по использованию C++11 и C++14

Там понятным языком разжевано что такое std::move и что надо прописать в классе чтобы он работал. Читать немного, 10-20 страниц.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632599
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivИ зачем ты туда new всобачил?
Чтобы запутать ещё больше?Не понял вопроса.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632658
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Trdb_dev, в этой книжке Эффективный и современный С++. 42 рекомендации по использованию C++11 и C++14 написано как устроен std::move. Он "работает" во время компиляции.Как еще должен "работать" обычный шаблон, как не во время компиляции? И причем тут, вообще, шаблон std::move?
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632906
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devненаследованные (собственные) члены конструктор копирования по умолчанию может и обычным копированием сделать через MOVSB, задав в регистрах #SI и #DI источник и приемник соответственно
НЕ НАДО так делать! В случае с копированием двух объектов одного класса может быт ещё ничего плохого не произойдёт, но в общем случае можно закосячить объект.

Во-первых, в объект входит указатель на виртуальную таблицу методов, если есть (это MS)
Во-вторых, если есть родительские методы, то &x и реальное начало данных x могут отличаться.
Плюс ещё оптимизатор, вроде, может чего-нить местами переставить.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39632971
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CEMbВо-первых, в объект входит указатель на виртуальную таблицу методов, если есть (это MS)
Плюс ещё оптимизатор, вроде, может чего-нить местами переставить.Собственно, указатель this, это указатель на указатель на таблицу виртуальных методов - это еще в Borland TASM было.
CEMbВо-вторых, если есть родительские методы, то &x и реальное начало данных могут отличаться.Не может! У экземпляра класса есть лишь одна таблица виртуальных методов, которая хранится отдельно от экземпляра класса и все экземпляры одного и того же класса имеют один и тот же указатель на таблицу виртуальных методов. При наследовании, компилятор создает копию родительской таблицы виртуальных методов и добавляет в конец этой копии указатели на виртуальные методы наследника в порядке их объявления. Конец таблицы виртуальных методов определяется указателем NULL.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39633478
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev, ну, может на счёт второго я и напутал что-то, я не смог вспомнить пример. Но первого достаточно, чтобы не копировать память вручную. Это потенциальная ошибка, у тебя могут быть пара указателей на класс А, один из которых на самом деле указывает на дочерний класс В. В случае прямого копирования получится неправильный экземпляр.
Хотя, интересный хак получается :)
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39633557
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CEMbrdb_dev, ну, может на счёт второго я и напутал что-то, я не смог вспомнить пример. Но первого достаточно, чтобы не копировать память вручную. Это потенциальная ошибка, у тебя могут быть пара указателей на класс А, один из которых на самом деле указывает на дочерний класс В. В случае прямого копирования получится неправильный экземпляр.
Хотя, интересный хак получается :)Почему должен получится неправильный экземпляр? Давай рассмотрим простой пример:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
class A
{
  a1 UINT64;
  a2 UINT32;

  A(const A & a)
  {
    size_t dataSz = (size_t)this->a2 + sizeof(A::a2) - (size_t)this->a1;
    ::memcpy(&this->a1, &a->a1, dataSz);
  };
}

class B : public A
{
  b1 UINT32;
  b2 UINT64;
}

int _cdecl main(int argc, char* argv[])
{
  auto b = new B();
  auto a = new A(*dynamic_cast<A>(b));
}

В соответствии с ABI, экземпляр B в памяти будет выглядеть следующим образом (на x86_32 при выравнивании на QWORD):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
 +0: B::vtbl_ptr
 +4: align space
 +8: a1
+16: a2
+20: align space
+24: b1
+28: align space
+32: b2
+40: out of instance

Поэтому, конструктор копии экземпляра A скопирует именно ту часть, которую должен. Вообще, я предпочитаю объединять члены класса в структуру - так проще копировать, если нет необходимости делать копии того, на что указывают члены-указатели, а для конструктора пересылки это идеальный вариант.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39633564
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Недавно обсуждали что std::string нельзя просто скопировать для переноса.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39633584
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T, конечно, экземпляры чужих классов нехорошо просто копировать, особенно, если не знаешь как они устроены, это ежу понятно! Но создать реализацию конструктора пересылки своего класса, которая будет копировать данные байт-в-байт, а затем подчищать источник - вполне допустимо.
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39633624
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devПочему должен получится неправильный экземпляр?потому что vtable pointer от одного класса перезапишется поверх vtp другого класса. Если использовать this-ы.

rdb_devДавай рассмотрим простой пример:а, ты какой хитрый!
ты берёшь адрес с переменной.
а это ещё хуже, потому что напишешь копировальщик. А потом забудешь, будешь рефакторить и перед a1 поставишь какую-нить другую переменную - и получится трудноуловимая ошибка.

Нет, я согласен, так делать можно при должной осторожности . Но я бы лично так не делал. Выгода не понятна, сомневаюсь в наличии таких классов, у которых movsb даст много выигрыша по сравнению с по-переменным копированием. Если в классе есть большие блоки данных (массивы, векторы), у них свой копировальщик. Все остальные копируются вручную.

Кстати, а что будет, если shared_ptr так скопировать? Т.е. понятно, что счётчик не увеличится, но что будет когда объект класса содержащего копию этого shared_ptr будет уничтожен?
...
Рейтинг: 0 / 0
2 раза вызывается деструктор
    #39633687
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CEMbпотому что vtable pointer от одного класса перезапишется поверх vtp другого класса. Если использовать this-ы.Естественно, копировать указатель на таблицу виртуальных методов не стОит! Он и так нормально проинициализируется.
CEMbа, ты какой хитрый!
ты берёшь адрес с переменной.Конечно! Что же еще? 😊
CEMbа это ещё хуже, потому что напишешь копировальщик. А потом забудешь, будешь рефакторить и перед a1 поставишь какую-нить другую переменную - и получится трудноуловимая ошибка.Поэтому, я и написал, что предпочитаю засовывать всё мемберы в инкапсулируемую структуру. Её проще копировать и даже можно написать inline конструктор копии или конструктор пересылки такой структуры.
CEMbНет, я согласен, так делать можно при должной осторожности . Но я бы лично так не делал. Выгода не понятна, сомневаюсь в наличии таких классов, у которых movsb даст много выигрыша по сравнению с по-переменным копированием. Если в классе есть большие блоки данных (массивы, векторы), у них свой копировальщик. Все остальные копируются вручную.Представь, что у тебя не три и не четыре члена, размером не более размерности регистра платформы, которые компилятор может распихать в регистры EAX, EDX, ECX, EBX, а гораздо больше и, к примеру, все long long, а приложение 32-х разрядное. Я пихаю все члены в структуру, чтобы не пропустить в конструкторе копии или пересылки какой-нибудь член, а гарантировано всё скопировать. Для конструктора пересылки это вполне нормальный подход, так как после копирования можно просто заполнить структуру источника нолями, что позволит обнулить и указатели, чтобы деструктор не освободил данные, которыми уже владеет объект-приемник.
CEMbКстати, а что будет, если shared_ptr так скопировать? Т.е. понятно, что счётчик не увеличится, но что будет когда объект класса содержащего копию этого shared_ptr будет уничтожен?Не надо просто копировать shared_ptr - он на это не расчитан. Другое дело, если ты создаешь свой собственный класс safe-thread смарт-указателя и чтобы при возврате его как rvalue через стек не дёргать каждый раз переменную подсчёта ссылок в синглетоне через медленные атомарные операции работы с памятью, ты можешь написать конструктор пересылки, который будет лишь копировать данные из источника и обнулять источник. Но это при условии, что синглетон типа не содержит реализацию реферальных ссылок на смарт-указатели.
...
Рейтинг: 0 / 0
12 сообщений из 37, страница 2 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / 2 раза вызывается деструктор
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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