Re[2]: вызов конструктора для элементов массива
От: Roman Odaisky Украина  
Дата: 24.04.06 12:24
Оценка: 9 (1)
Здравствуйте, sch, Вы писали:

sch>
sch>class B {
sch>  char aaa_buffer[100 * sizeof(A)];
sch>  A *aaa;

sch>  B() {
sch>    aaa = (A *) aaa_buffer;

sch>    A *p = aaa;
sch>    for(int i = 0; i < 100; i++, p++) new (p) A(some_int_parameter);
sch>  }
sch>};

sch>

Опасно, даже очень.

1) alignment
2) деструкторы придется вызывать ручками

Или я не прав?
До последнего не верил в пирамиду Лебедева.
Re: вызов конструктора для элементов массива
От: sch  
Дата: 24.04.06 09:40
Оценка: 2 (1)
Здравствуйте, Окунь, Вы писали:

О>Как-то столкнулся с проблемой.

О>Есть два класса:

О>class A

О>{
О> A(int);
О> A(float);
О>};

О>Можно ли написать конструктор класса B, чтобы для элементов массива B::а он не пытался вызвать конструктор по умолчанию, а вызывал бы, например, А(int); ?


class B {
  char aaa_buffer[100 * sizeof(A)];
  A *aaa;

  B() {
    aaa = (A *) aaa_buffer;

    A *p = aaa;
    for(int i = 0; i < 100; i++, p++) new (p) A(some_int_parameter);
  }
};
Re: вызов конструктора для элементов массива
От: Bell Россия  
Дата: 24.04.06 09:41
Оценка: 2 (1)
Здравствуйте, Окунь, Вы писали:


О>Можно ли написать конструктор класса B, чтобы для элементов массива B::а он не пытался вызвать конструктор по умолчанию, а вызывал бы, например, А(int); ?


Нет, нельзя. Массив всегда инициализирует свои элементы вызовом конструктора по умолчанию.
Проблему можно обойти, если воспользоваться, например, std::vector:

#include <vector>

class A
{
public:
A(int) {}
A(float) {}
};

class B
{
std::vector<A> aaa;
public:
B() : aaa(100, A(1)) {}
};
Любите книгу — источник знаний (с) М.Горький
Re: Solution
От: remark Россия http://www.1024cores.net/
Дата: 24.04.06 17:49
Оценка: 2 (1)
Здравствуйте, Окунь, Вы писали:

О>Как-то столкнулся с проблемой.

О>Есть два класса:

О>class A

О>{
О> A(int);
О> A(float);
О>};

О>class B

О>{
О> B();
О> A aaa[100];
О>};

О>Можно ли написать конструктор класса B, чтобы для элементов массива B::а он не пытался вызвать конструктор по умолчанию, а вызывал бы, например, А(int); ?


О>B::B()

О>: //a ???
О>{
О>}



Ну прямо таки нельзя?

struct A
{
    A(int i) : i_(i) {}
    int i_;
};

template<int I>
struct B : A
{
    B() : A(I) {}
};


B<55> arr[100]; // Создали массив А, в конструктор передаётся 55



Это частное решение. В принципе можно попробовать как-то обобщить.




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
вызов конструктора для элементов массива
От: Окунь  
Дата: 24.04.06 09:29
Оценка:
Как-то столкнулся с проблемой.
Есть два класса:

class A
{
A(int);
A(float);
};

class B
{
B();
A aaa[100];
};

Можно ли написать конструктор класса B, чтобы для элементов массива B::а он не пытался вызвать конструктор по умолчанию, а вызывал бы, например, А(int); ?

B::B()
: //a ???
{
}
Re[3]: вызов конструктора для элементов массива
От: VoidEx  
Дата: 24.04.06 16:48
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, sch, Вы писали:


sch>>[/c]

RO>Опасно, даже очень.

RO>1) alignment

RO>2) деструкторы придется вызывать ручками

RO>Или я не прав?

Прав, ну тогда


type arr[100];
for (unsigned int i = 100; i--;)
{
  arr[i].~type();
  new (&arr[i]) type(100);
}


Re: Super Solution
От: remark Россия http://www.1024cores.net/
Дата: 24.04.06 20:08
Оценка:
Здравствуйте, Окунь, Вы писали:

О>Как-то столкнулся с проблемой.

О>Есть два класса:

О>class A

О>{
О> A(int);
О> A(float);
О>};

О>class B

О>{
О> B();
О> A aaa[100];
О>};

О>Можно ли написать конструктор класса B, чтобы для элементов массива B::а он не пытался вызвать конструктор по умолчанию, а вызывал бы, например, А(int); ?


О>B::B()

О>: //a ???
О>{
О>}



Super Solution (сочетает приемущества статического массива и возможности вызвать произвольный конструктор для объектов за счёт явного разделения фазы создания хранилища и инициализации):


template<typename Type, size_t Size>
class SuperArray
{
private:
    boost::aligned_storage<Size * sizeof(Type), boost::alignment_of<Type>::value> arr_;

public:
    template<typename P1>
    SuperArray(P1 p1)
    {
        for (size_t i = 0; i < Size; ++i)
            new (&((reinterpret_cast<Type*>(arr_.address()))[i])) Type(p1);
    }

    template<typename P1, typename P2>
    SuperArray(P1 p1, P2 p2)
    {
        for (size_t i = 0; i < Size; ++i)
            new (&((reinterpret_cast<Type*>(arr_.address()))[i])) Type(p1, p2);
    }

    // ... И т.д. Желательно заюзать BOOST_PP

    ~SuperArray()
    {
        for (size_t i = 0; i < Size; ++i)
            ((reinterpret_cast<Type*>(arr_.address()))[i]).Type::~Type();
    }

    Type& operator [] (size_t i)
    {
        return ((reinterpret_cast<Type*>(arr_.address()))[i]);
    }

    const Type& operator [] (size_t i) const
    {
        return ((reinterpret_cast<Type*>(arr_.address()))[i]);
    }
};



Использование:

struct A
{
    A(int i) : i_(i) {}
    A(int i, bool b) : i_(i), b_(b) {}
    bool b_;
    int i_;

    static void* operator new (size_t, A* p)
    {
        return p;
    }

    static void operator delete (void* p, A*)
    {
    }
};

SuperArray<A, 100> arr1(15);

SuperArray<A, 100> arr2(59, true);




Пока только до конца не понял, достаточно ли хранить как:
boost::aligned_storage<Size * sizeof(Type), boost::alignment_of<Type>::value> arr_;


Или всё-таки обязательно надо:
boost::aligned_storage<sizeof(Type), boost::alignment_of<Type>::value> arr_[Size];



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Super Solution
От: Roman Odaisky Украина  
Дата: 24.04.06 20:18
Оценка:
Здравствуйте, remark, Вы писали:


R>Super Solution (сочетает приемущества статического массива и возможности вызвать произвольный конструктор для объектов за счёт явного разделения фазы создания хранилища и инициализации):


Ну намутил!.. Это все один большой грязный хак. Автору надо хорошенько задуматься над выбором структуры данных, авось и велосипеды, комбинированные с граблями, не понадобятся. Кстати, тому конструктору, у которого один аргумент, не помешало бы explicit.

R>Пока только до конца не понял, достаточно ли хранить как:

R>
R>boost::aligned_storage<Size * sizeof(Type), boost::alignment_of<Type>::value> arr_;
R>


R>Или всё-таки обязательно надо:

R>
R>boost::aligned_storage<sizeof(Type), boost::alignment_of<Type>::value> arr_[Size];
R>


А чем не нравится второе? Как-то выглядит понадежнее.
До последнего не верил в пирамиду Лебедева.
Re[2]: Solution
От: Окунь  
Дата: 26.04.06 12:10
Оценка:
Здравствуйте, remark, Вы писали:

R>Ну прямо таки нельзя?


R>
R>struct A
R>{
R>    A(int i) : i_(i) {}
R>    int i_;
R>};

R>template<int I>
R>struct B : A
R>{
R>    B() : A(I) {}
R>};


R>B<55> arr[100]; // Создали массив А, в конструктор передаётся 55
R>



R>Это частное решение. В принципе можно попробовать как-то обобщить.




Просто и со вкусом.
А до использования SuperArray я еще не дорос
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.