开发者

Constructing "array" of noncopyable objects

开发者 https://www.devze.com 2023-03-07 03:41 出处:网络
I have a class that\'s inhenerently non-copyable (a thread, so there\'s no copy semantics that make sense), and I want to have a largeish \'array\' of these, identically constructed with a non-default

I have a class that's inhenerently non-copyable (a thread, so there's no copy semantics that make sense), and I want to have a largeish 'array' of these, identically constructed with a non-default constructor. Note that the array is fixed size.

I can only use the default constructor with C++ arrays, unless I initialise each one independently.

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

I can list the object constructors and parameters explicitly, but that's verbose and ugly

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

It seems I can't use stl vectors because the object is non-copyable - event though the vector never changes size. I guess the constructor actually does copying!

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

The way I've though of doing this is with an开发者_运维知识库 array of smart pointers and an initialization loop, but maybe I'm missing something:

Is there any other way - maybe with boost containers, or a different container type?


This may seem like totally crazy (and it probably is), but...

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];
}

Maybe this works out for you. :) Of course, you now need to watch out if the array is initialized in multithreaded code itself...


A vector of smart pointers, with each instance dynamically allocated, is definitely the simplest way. Otherwise (and I'd only do this if absolutely necessary), you can more or less emulate what std::vector does internally. Something along the lines of:

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) );
}

(I'd actually wrap this in a class, if only to be able to use operator[] instead of getAt.)


For new compilers supporting r-value references, being copyable is not necessary for vector elements AFAIK. To use it without copying 128 push_back's should be used (creating new object each time), because creting several objects from a single one is a copying :).

If this way is not available, try boost::ptr_vector or std::vector of boost::shared_ptr.


I am not that much big programmer. But did you try this

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

精彩评论

暂无评论...
验证码 换一张
取 消