Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Использование * new в конструкторе копирования, для условной инициализации 
V
    Опции темы
marcusmae
Дата 1.4.2008, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



Всем привет,

Сразу прошу не пугаться, если что smile 

Назову условной инициализацией следующее : 

Код

class A : B {

    A(bool flag) :

    B(flag ? ... : ...) 

    { ... }

};


- Условное выражение в аргументе конструктора копирования класса B. А вот что может стоять на месте троеточий - аргументов? = Я так понимаю, что указатели на B. Причём такие, чтобы не возникло никаких проблем с динамическими членами.

Следующий вариант не проходит :

Код

B(flag ? ... : B(...))


потому что автоматический экземпляр при первой возможности удалится вместе со своими динамическими членами. Как же быть? Наверно, так :

Код

B(flag ? ... : * new B(...))


- нормально?

Это сообщение отредактировал(а) marcusmae - 1.4.2008, 14:52


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Lazin
Дата 1.4.2008, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



нет

Добавлено через 29 секунд
какая сигнатура конструктора В, что он получает?

Добавлено через 5 минут и 20 секунд
как вариант:

Код

template<int val> int2type
{
  const int value = val;
};

class A : B
{
 A(int2type<0>) : B(....первый вариант конструктора...) {}
 A(int2type<1>) : B(....второй вариант конструктора...) {}
....
};


но в этом случае на этапе компиляции тип конструктора должен быть известен((

PM MAIL Skype GTalk   Вверх
marcusmae
Дата 1.4.2008, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



Цитата(Lazin @  1.4.2008,  14:51 Найти цитируемый пост)
какая сигнатура конструктора В, что он получает?


Ну аргументы какие-то ему перепадают из конструктора A. Правильнее так :

Код

class A : B {

    A(const bool flag, ... /* some args */) :

    B(flag ? ... : ...) 

    { ... }

};


Мне такая штука в нескольких разных местах нужна. 

Это сообщение отредактировал(а) marcusmae - 1.4.2008, 14:58


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Lazin
Дата 1.4.2008, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(marcusmae @  1.4.2008,  14:50 Найти цитируемый пост)
потому что автоматический экземпляр при первой возможности удалится вместе со своими динамическими членами. Как же быть?

наверное написать для  B копирующий конструктор 
PM MAIL Skype GTalk   Вверх
marcusmae
Дата 1.4.2008, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



Цитата(Lazin @  1.4.2008,  14:51 Найти цитируемый пост)
но в этом случае на этапе компиляции тип конструктора должен быть известен((


Нет-нет, извините, не катит. Не перемещайте, пожалуйста, инициализацию в тело конструктора. Речь идёт именно о том, чтобы она находилась в initialization-list-е - после двоеточия. В чём конкретно состоит проблема моего варианта? Он рабочий, но очень может быть, что я не вижу какие-то подводные камни...


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Lazin
Дата 1.4.2008, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(marcusmae @  1.4.2008,  15:02 Найти цитируемый пост)
Он рабочий, но очень может быть, что я не вижу какие-то подводные камни... 

утечку памяти smile
PM MAIL Skype GTalk   Вверх
marcusmae
Дата 1.4.2008, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



Цитата(Lazin @  1.4.2008,  14:58 Найти цитируемый пост)
наверное написать для  B копирующий конструктор


Да, можно копировать, но как-то излишне, по-моему. В моём фрагменте специально под экземпляр класса A для исключительного использования создаётся экземпляр B. Ну и зачем его копировать, если можно просто взять ссылку?..

Цитата(Lazin @  1.4.2008,  15:04 Найти цитируемый пост)
утечку памяти

Откуда? - Покажите, пожалуйста.



--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Earnest
Дата 1.4.2008, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Не получится. Разные конструкторы - разные функции, компилятор должен знать, какой конструктор подставить в момент компиляции, и динамическое значение флага ему до лампочки. Флаг может определять только конкретное значение аргумента.

Вариант
Цитата(marcusmae @  1.4.2008,  15:50 Найти цитируемый пост)
B(flag ? ... : * new B(...))

ужасен и сам по себе (из-за мемори-ликов): кроме того, здесь именно и происходит вызов копирующего конструктора, которого ты так не хочешь. Причем в первой части тоже должен быть аргумент типа B&.

Если бы у тебя было не наследование, а просто указатель на B, то можно было бы написать так:
B (flag ? new B (...) : new B()) - т.е. использовать разные конструкторы.

Если твой флаг является константой, известной в момент компиляции, то можно сделать условную инициализацию с помощью шаблона.

Добавлено через 1 минуту и 11 секунд
Цитата(marcusmae @  1.4.2008,  16:08 Найти цитируемый пост)
Откуда? - Покажите, пожалуйста.

Кто разрушит указатель, созданный new?


--------------------
...
PM   Вверх
marcusmae
Дата 1.4.2008, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



Цитата(Earnest @  1.4.2008,  15:12 Найти цитируемый пост)
Если твой флаг является константой, известной в момент компиляции, то можно сделать условную инициализацию с помощью шаблона.


Нет, не является.

Цитата(Earnest @  1.4.2008,  15:12 Найти цитируемый пост)
Кто разрушит указатель, созданный new?

Понял, есть проблема.

Цитата(Earnest @  1.4.2008,  15:12 Найти цитируемый пост)
Причем в первой части тоже должен быть аргумент типа B&.


Конечно, либо тоже конструктор, как Вы заметили, либо какая-нибудь статическая функция, возвращающая const B&.

Хорошо, допустим, я пишу копирующий конструктор, но реально копирую в нём только автоматические члены, в т.ч. указатели. Динамически выделенную память - с помощью внутренних флагов указываю, что её не должен удалять экземпляр-оригинал, но должен экземпляр-копия. Нормально?

Цитата(Earnest @  1.4.2008,  15:12 Найти цитируемый пост)
Если бы у тебя было не наследование, а просто указатель на B


Наследование чем-то хуже?..

Это сообщение отредактировал(а) marcusmae - 1.4.2008, 16:02


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
korian
Дата 1.4.2008, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



Цитата(marcusmae @  1.4.2008,  14:08 Найти цитируемый пост)
Да, можно копировать, но как-то излишне, по-моему. В моём фрагменте специально под экземпляр класса A для исключительного использования создаётся экземпляр B. Ну и зачем его копировать, если можно просто взять ссылку?..

тут два варианта, зависит от того, что из себя представляют объекты A и B.
если тут действительно необходимо наследование, то надо писать копирующий конструктор. и забыть про то, что это дает "излишнее" копирование. компилятор сам сделает нужную оптимизацию.
если наследование тут просто "прикручено", то убрать его и использовать указатели.

Добавлено через 5 минут и 47 секунд
хотя если объект B имеет не тривиальные данные, то полюбому надо описывать копирующий конструктор.
или реализовывать его, или объявлять его в приват секции.

Это сообщение отредактировал(а) korian - 1.4.2008, 17:22
PM   Вверх
Earnest
Дата 2.4.2008, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(marcusmae @  1.4.2008,  16:33 Найти цитируемый пост)
Наследование чем-то хуже?..

Это просто пример. Кроме того, наследование действительно хуже включения, потому что образует более тесную зависимость. Но иногда действительно оно нужно.
Допустим, это твой случай - нужно именно наследоваться.

Вариант 1: плюнуть на доп. расходы, связанные с конструктором копировани (всякие флаги - не уничтожать указатель и прочее - ОЧЕНЬ ПЛОХОЙ ВАРИАНТ). Очень мало случаев, когда нельзя наплевать на какое-то там лишнее копирование. А преждевременная оптимизация есть ЗЛО.

Вариант 2: сделать конструктор B пустым (один из) и инициализировать его в теле конструктора, написав одну или больше функций типа Сonstruct. И не надо говорить, что этого нельзя сделать - сделать можно все... почти... smile 




--------------------
...
PM   Вверх
marcusmae
Дата 2.4.2008, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



Почитал, подумал, всё взвесил и понял, что раз корень зла - утечка памяти из-под new в аргументе, то почему бы не сохранить её в приватном поле? Для этого понадобилось ввести ещё один промежуточный конструктор, но не суть : как только ссылка подхвачена, её можно будет потом удалить через деструктор класса. Ну и свой конструктор копирования таки определил - тут Вы были правы smile В нём не копирую память, а переприсваиваю указатель. По-моему, достаточно безопасно. Если ничего плохого не замечу, то потом распространю это решение на все подобные случаи.


Earnest, Lazin, korian, спасибо!


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Earnest
Дата 3.4.2008, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Вообще-то не за что. Судя по твоему посту, мы тебя не убедили - решение ты принял плохое... Ну, значит, будешь учится на своих ошибках, раз чужому опыту не веришь... smile 


--------------------
...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0771 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.