Вызов конструктора для массива классов.

Тема в разделе "LANGS.C", создана пользователем KeSqueer, 6 июл 2009.

  1. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Разбирал одну либу, столкнулся со следующим.
    Есть класс VDisk, в нем есть массив классов VFile (постоянное число). В конструкторе VDisk'а вызывается конструктор VFile'а для каждого элемента массива, но не через цикл, а с помощью передачи в некоторую функцию указателя на массив классов, размера одного элемента (класса), числа элементов (классов) и указателей на конструктор и деструктор VFile'а. Причем вызываемая функция была одмечена IDA как библиотечная. Как это осуществляется средствами языка?
     
  2. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Смахивает на Placement New.
     
  3. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    std::vector ?
     
  4. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    s0larian
    приведи пример плз
     
  5. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    Эээ... C++ знаешь?

    Код (Text):
    1. struct Shite
    2. {
    3. Shite()
    4. : m_something(0)
    5. {
    6. }
    7.  
    8. int m_something;
    9. };
    10.  
    11. void func()
    12. {
    13.     std::vector<Shite> v;
    14.     v.resize(65);
    15. }
     
  6. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    P.S. Это не совсем "средствами языка". Это средствами стандартной библиотеки.
     
  7. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    s0larian
    нет, а запостил отедльно от "начинающих в с/с+", т.к. побыстрее хотел получить ответ)

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

    Код (Text):
    1. class B
    2. {
    3. public:
    4.     B () {};
    5. };
    6.  
    7. class A
    8. {
    9. public:
    10.     A() : b() { };
    11.     B b[N];
    для инициализации b вызывается
    Код (Text):
    1. void __stdcall `vector constructor iterator'(void *,unsigned int,int,void * (__thiscall*)(void *))
    Как сделать это внутри тела функции, хоть это вроде и не нужно, - не знаю. Так не компилируется:

    Код (Text):
    1. class A
    2. {
    3. public:
    4.     A() {b();};
    5.     B b[N];
     
  8. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    ну там это, закрывающие скобки еще добавить...
    ВЕРНИТЕ РЕДАКТИРОВАНИЕ, ЧЕМ ОНО МЕШАЛО?
     
  9. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    Это не скомпилится, т.к. нужна константа. Просто заполненный массив:

    Код (Text):
    1. void func()
    2. {
    3.     Shite temp[16]; // stack
    4.     Shite *temp2 = new Shite[16]; // heap
    5. }
     
  10. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Это в конструкторе, наверное, одно из первых действий? Так просто компилятор так код генерит. Вот, тот же эффект должен наблюдаться при дизассемблировании (осторожно с оптимизацией только):
    Код (Text):
    1. class A
    2. {
    3. public:
    4.     int x;
    5.     A() { x = 1; }
    6.     B b[2000];
    7. };
    8.  
    9. int main()
    10. {
    11.     A a;        // call `vector constructor iterator'(),     a.x = 1.
    12. }
     
  11. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    s0larian
    а) N - ессно константа.
    б) В последнем моем посте я имел в виду, что нельзя в теле функции-конструктора написать A() { b(); }
    а выше (не знаю как это называется) после круглых скобок через двоеточие можно:
    A() : b() {}, и это компилятор превратит в вызов функции отвечающей за вызов конструктора для каждого элемента массива.

    в) Shite *temp2 = new Shite[16]; // heap
    тоже, кстати, сводится к вызову 'vector constructor iterator', но здесь есть еще выделение памяти, в то время как в моем случае память уже была выделена.


    Sol_Ksacap
    а) да, это одно из первых действий. Первые два - инициализация стекового фрейма и установка обработчика исключений :) Но это и объясняется: A() : b() {}.
    б) В Вашем примере 'vector constructor iterator' не будет вызван, т.к. эта функция отвечает за инициализацию массива классов. Компилировал без оптимизации, все свелось к "a.x = 1;".


    P.S.
    а) Вроде бы старался в первом посте писать не двусмысленно. Откуда недопонимание? Надо было сразу приводить код, а в конце поставить знак "?".
    б) я плохо объясняю, тут лучше: http://members.ozemail.com.au/~geoffch@ozemail.com.au/samples/programming/msvc/language/compgen/
     
  12. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Возникла новая проблема - как вызвать деструктор для всех элементов массива используя 'vector destructor iterator', не в начале функции-деструктора? Но она быстро разрешилась:
    Код (Text):
    1. class B {
    2. public:
    3.     B() {};
    4.     ~B() {};
    5. };
    6.  
    7. class A
    8. {
    9. public:
    10.     A() : b() {};
    11.     ~A() { b->~B();}
    12.     B b[8];
    13. };
    14.  
    15.  
    16. int _tmain(int argc, _TCHAR* argv[])
    17. {
    18.     A a;
    19. }
     
  13. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Всё таки я склоняюсь к Placement New(конструирование с разделение фаз).
    Код (Text):
    1. #include <iostream>
    2.  
    3. class Test
    4. {
    5. public:
    6.     Test()
    7.     {
    8.         std::cout<<m_counter++<<std::endl;
    9.     }
    10.     void* operator new[] (size_t, void* p)
    11.     {
    12.         return p;
    13.     }
    14. private:
    15.     static int m_counter;
    16. };
    17.  
    18. int Test::m_counter = 0;
    19.  
    20. int main()
    21. {
    22.     const int countObj = 10;
    23.     void *p= malloc(sizeof(Test)*countObj);
    24.     Test *pTestArray = new (p) Test[countObj];
    25. }
     
  14. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Хотя чем не устраивает простое new[]?
     
  15. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    KeSqueer
    Надо было быть осторожнее с оптимизацией. Ещё осторожнее, ага.


    Код (Text):
    1. // main3.cpp
    2. //
    3. // cl main3.cpp kernel32.lib /Zi /link /entry:main
    4. //
    5. #include <windows.h>
    6.  
    7. class B
    8. {
    9. public:
    10.     B(){ CloseHandle((HANDLE)this); }
    11. };
    12.  
    13. class A
    14. {
    15. public:
    16.     A(){ x = 1; }
    17.     int x;
    18.     B b[2000];
    19. };
    20.  
    21. int main()
    22. {
    23.     A a;
    24. }
    // http://img32.imageshack.us/img32/3198/sshot37.png
    [​IMG]

    Как видно по картинке, всё вызывается само в рамках конструктора. С деструктором то же самое – не нужно никаких ухищрений вроде A() : b() {}; или ~A() { b->~B();}.
     
  16. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Однако) Видимо при первом тесте забыл определить конструктор B в первом случае и деструктор - во втором, поэтому функции не вызывались. Спасибо, а то бы я продолжал использовать : b() и b->~B().
     
  17. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    Что за дизассемблер кстати?
     
  18. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Ноу проблем :)

    Olly. Схему цветовую только сменили и подсветку кода отключили. Из-за, лайк, внезапного приступа паранойи.
     
  19. reversecode

    reversecode Guest

    Публикаций:
    0
    Код (Text):
    1. class B {
    2. public:
    3.     B() {};
    4.     ~B() {};
    5. };
    6.  
    7. class A
    8. {
    9. public:
    10.     A() : b() {};
    11.     ~A() { b->~B();}
    12.     B b[8];
    13. };
    14.  
    15.  
    16. int _tmain(int argc, _TCHAR* argv[])
    17. {
    18.     A a;
    19. }
    все правильно токо b-> вызывать нинадо
    тоесть

    Код (Text):
    1. class B {
    2. public:
    3.     B() {};
    4.     ~B() {};
    5. };
    6.  
    7. class A
    8. {
    9. public:
    10.     A() {};
    11.     ~A() {}
    12.     B b[8];
    13. };
    14.  
    15.  
    16. int _tmain(int argc, _TCHAR* argv[])
    17. {
    18.     A a;
    19. }
     
  20. reversecode

    reversecode Guest

    Публикаций:
    0
    скорее не библиотечная а встроеная для своих нужд компилятору

    точные параметры функции не пе помню и да их таких фунций бывает два вида
    первая используеться в конструкторах для создания массивов
    аргументы указатели на конструктор и деструктор класса
    и количество алементов
    ну и указатель на таблицу зис
    и что то еще- уже не помню

    и в деструторе
    для уничтожение тогоже массива
    все точно так же
    токо не передаеться адресс фунции конструктор класса