LINUX.ORG.RU

Вопрос про конструктор С++: массив объектов


0

0

Предположим, есть класс

class A;

Скажем, нас интересует конструктор A(int k). Теперь, нужно работать с массивом объектов A:

A* ar;

ar = new A[sz_a_num];

Получается, что ведь не только выделится память, но и запустится конструктор для каждого объекта (тот, который по умолчанию). А как запустить тот конструктор, который нужно? Неужели только через указатели? Отдельная проблема состоит в том, что желательно передать разные параметры разным объектам.

>A* ar;

>ar = new A[sz_a_num];

>Получается, что ведь не только выделится память, но и запустится конструктор для каждого объекта (тот, который по умолчанию). А как запустить тот конструктор, который нужно

ar = new A[sz_a_num](int k);

>Отдельная проблема состоит в том, что желательно передать разные параметры разным объектам.

массив указателей в руки, и вручную инициализировать каждый элемент.

wfrr ★★☆
()
Ответ на: комментарий от wfrr

Спасибо, я в общем-то так и предполагал. Небольшое добавление в функционал класса A (назовем это "отложенной" инициализацией) фактически решило эту проблему, но хотелось ведь сделать красиво:)

А массив указателей для данной задачи - это чрезмерно.

Alexey-ZAR
() автор топика
Ответ на: комментарий от Alexey-ZAR

Можете сделать статический метод, получающий список параметров конструктора и возвращающий массив обьектов класа. Но красиво это всеравно не будет тк нужно будет все это удалять. Вижу выход лишь во враппере но оно надо?

anonymous
()

Запустится конструктор по-умолчанию. Поскольку в массиве будут объекты-значения. Чтобы были разные параметры для конструктора - нужно использовать указатели. Да, и вообще, любой учебник по языку должен покрывать эту тему...

dave ★★★★★
()
Ответ на: комментарий от Alexey-ZAR

> А массив указателей для данной задачи - это чрезмерно.

массив указателей не нужен.  Нужно выделить память для массива и пройтись в цикле по нему в ручную вызвав конструктор (placement new):

A *arr = (A *)malloc(sizeof(A) * 100);
for (int i = 100; i--; )
{
  new(arr + i)(A)(ctor args);
}

вместо ctor args подставить аргументы конструктора.

dilmah ★★★★★
()

Еще можно и нужно использовать std::vector

std::vector<A> ar(sz_a_num, A(17));

fghj ★★★★★
()
Ответ на: комментарий от dilmah

malloc можно заменить на:

A *arr = A::operator new[](sizeof(A)*100);

operator new (в отличие от инструкции new) не вызывает конструктор, а только аллоцирует память.

dilmah ★★★★★
()
Ответ на: комментарий от dave

всегда была, еще до стандарта.

я просто наврал немножко:) -- по дефолту есть глобальный operator new:

A *arr = (A *)operator new(sizeof(A));

Для класса дефолтного operator new нет, его можно только определить.

Ну а инструкция new означает сперва вызов какого-то operator new (возможно с дополнительными аргументами) и потом вызов конструктора.

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

Ясно. Но все же решение отдает очень сильным хардкором. Выделять память, а потом вручную специфически вызывать конструктор по уже выделенным кускам памяти... Это сильно.

Просто я тут решил восполнить свое незнание новых возможностей Ada'95 и Ada'05. Когда-то, еще будучи школьником в конце 80-x фанател от Ada'83. В общем, такой сишный (++) хардкор резко отличается от трогательной и просто отеческой заботы компилятора Ada над каждой инструкцией, правда, часто ограничиваясь лишь compile-time. Какой контраст!

dave ★★★★★
()
Ответ на: комментарий от dave

> решение отдает очень сильным хардкором.

Решение отдает хорошей производительностью. Спасибо Дилме, я тоже не знал что так можно сделать!

anonymous
()
Ответ на: комментарий от anonymous

Ну, вот, оговорился... :) Просто я очень консервативен в этом вопросе.

dave ★★★★★
()
Ответ на: комментарий от dave

> Ясно. Но все же решение отдает очень сильным хардкором. Выделять память, а потом вручную специфически вызывать конструктор по уже выделенным кускам памяти... Это сильно.

это может быть актуальным если, например, объект расположен в разделяемой памяти и соотв. просто так сказать new foo; нет возможности но конструктор таки хочется вызвать.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> если, например, объект расположен в разделяемой памяти

В принципе он и в ПЗУ при таком раскладе может сидеть, а при конструировании инициализировать чо-нить типа последовательного порта.

anonymous
()
Ответ на: комментарий от anonymous

> В принципе он и в ПЗУ при таком раскладе может сидеть, а при конструировании инициализировать чо-нить типа последовательного порта.

конструктор объекта предназначен скорее для инициализации внутренних структур этого объекта, что сделать несколько затруднительно, если объект расположен в ROM ;) опять же, инициализировать последовательный порт в конструкторе aka без привязки к экземпляру объекта - а не проще сделать инициализацию обычной функцией?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> а не проще сделать инициализацию обычной функцией?

По-моему это было бы самым правильным решением. Желательно еще чтобы дефолтный конструктор проработал бы быстро, а функция инициализации не конфликтовала бы с ним (чтобы не надо было пересоздавать массивы и объекты заново).

> это может быть актуальным если, например, объект расположен в разделяемой памяти и соотв. просто так сказать new foo; нет возможности но конструктор таки хочется вызвать.

Не совсем понял... Т.е. объект уже существует? Тогда зачем ему конструктор?! :)

dave ★★★★★
()
Ответ на: комментарий от dave

> Т.е. объект уже существует? Тогда зачем ему конструктор?! :)

Наверное имелось в виду то, что хочется создать объект в разделяемой памяти.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

С помощью new(addr)(A)(args) по заданному адресу addr? Это интересно.

dave ★★★★★
()
Ответ на: комментарий от Legioner

Теперь дошло. Похоже перечитался Ada 95 Rationale :)

dave ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.