Построение «массива» некопируемых объектов - PullRequest
7 голосов
/ 18 мая 2011

У меня есть класс, который по своей сути не подлежит копированию (поток, так что семантика копирования не имеет смысла), и я хочу иметь их большой массив, идентично созданный с помощью конструктора не по умолчанию. Обратите внимание, что массив имеет фиксированный размер.

Я могу использовать конструктор по умолчанию только с массивами C ++, если я не инициализирую каждый из них независимо.

Thread myArray[128];   // uses default constructor - wrong

Я могу перечислить конструкторы и параметры объекта в явном виде, но это многословно и безобразно

Thread myArray[128] = { Thread(params,...), Thread(params,...), ... x 128 ;  // ugly

Кажется, я не могу использовать векторы stl, потому что объект не подлежит копированию - событие, хотя вектор никогда не меняет размер. Я предполагаю, что конструктор действительно копирует!

std::vector<Thread> myVector(128, Thread(params,...));// won't compile

Я решил сделать это с помощью массива умных указателей и цикла инициализации, но, возможно, я что-то упускаю:

Есть ли другой способ - может быть, с буст-контейнерами или контейнером другого типа?

Ответы [ 4 ]

6 голосов
/ 18 мая 2011

Это может показаться совершенно сумасшедшим (и, вероятно, так оно и есть), но ...

struct ThreadInitValues{
  // your actual params
  int i;
  float f;
};

struct Thread{
    Thread(int i = _init.i, float f = _init.f)
      : _i(i)
      , _f(f)
    {}

    static ThreadInitValues _init;

private:
    // uncopyable
    Thread(Thread const&);
    Thread& operator=(Thread const& other);

    // your actual member
    int _i;
    float _f;
};

ThreadInitValues Thread::_init;

int main(){
    Thread::_init.i = 5;
    Thread::_init.f = 3.14f;
    Thread arr[128];
}

Может быть, это работает для вас. :) Конечно, теперь вам нужно следить за тем, инициализируется ли массив в самом многопоточном коде ...

3 голосов
/ 18 мая 2011

Вектор умных указателей, с каждым экземпляром динамически выделено, безусловно, самый простой способ. В противном случае (и я бы делать это только в случае крайней необходимости), вы можете более или менее подражать тому, что std::vector делает внутри. Что-то вдоль строки:

union
{
    double just_to_ensure_alignment;
    unsigned char data[ sizeof(Thread) * elementCount ];
} array;

//  construct...
for ( int i = 0; i != elementCount; ++ i )
    new (data + i * sizeof(Thread)) Thread(params,...);

//  access...
Thread& getAt( int i )
{
    return reinterpret_cast<Thread*>( data + i * sizeof(Thread) );
}

(я бы на самом деле обернул это в классе, если бы только мог operator[] вместо getAt.)

1 голос
/ 18 мая 2011

Для новых компиляторов, поддерживающих ссылки на r-значение, копирование не обязательно для векторных элементов AFAIK.Чтобы использовать его без копирования, необходимо использовать 128 push_back (создание нового объекта каждый раз), поскольку создание нескольких объектов из одного - это копирование:).

Если этот способ недоступенпопробуйте boost :: ptr_vector или std :: vector of boost :: shared_ptr.

0 голосов
/ 18 мая 2011

Я не очень большой программист.Но ты пробовал это

std::vector<YourObject *> temp_Vec;
for(int i=0;i<128;++i)
    temp_Vec.push_back(new YourObject(arguments));
...