0

I have some objects of a same class in an array that was pointed by a unique_ptr, and each object can only be created with the explicit constructor, since a few of arguments must be passed to the constructor.

When initializing, I'm going to create such a unique_ptr as following:

unique_ptr<ClassA [ ] >  arrayA = make_unique<ClassA [ ]>(100, some args to be passed );

But it looks like there is no version of make_unique can do so as above. According to docs: If make_unique is making a array, it only takes one argument that is the size of the array.

I can not use vector in this scenes, as the ClassA is a message queue that is being shared by multiple threads(productors/cosumers), while vector will move elements to a new place if the space is insufficient.

Is there another way, in it I can make a array of a class that has only explicit constructor? At same time, I still want to use unique_ptr to manage them.

Thanks!

Leon
  • 1,489
  • 1
  • 12
  • 31
  • 3
    What about using `std::vector` to manage them instead? – StoryTeller - Unslander Monica Jan 29 '19 at 06:24
  • Thank you. But my class is not movable. It is a message queue in the fact, and is shared by producters and consumers. Vector will move elements if the space is insufficient, but there are multiple threads that are reading/writing the queue. So I can not use a vector. – Leon Jan 29 '19 at 06:33
  • I don't really see what the threads have to do with this. No thread is going to access that array until you finish creating it (otherwise you have a serious design flaw). So just create the vector in advance (as you obviously intend to do here) and don't add or remove elements to it once its available. – StoryTeller - Unslander Monica Jan 29 '19 at 06:36
  • How about a `std::vector` of `std::shared_ptr`? – AchimGuetlein Jan 29 '19 at 06:42
  • 1
    _while vector will move elements to a new place if the space is insufficient_: If the space is insufficient, you have a problem with `unique_ptr` as well. Simply resize a vector before creating threads, or in a single thread only. – Daniel Langr Jan 29 '19 at 06:54
  • *"vector will move elements to a new place if the space is insufficient."* - But what will you do if your dynamic array is too small? A `std::vector` won't magically resize itself unless you tell it to. Just like a hand written dynamic array. – Galik Jan 29 '19 at 07:16
  • Thank all above gentlemen, sorry for my English, as I'm a Chinese. Indeed I was using a vector before, while I try to re-code today, because std::vector force me that a element must be CopyAssignable/CopyConstructible. I was worrying about it is not a good idea to make a message queue CopyConstructible/CopyAssignable, as I don't know when the element would be moving. It is the reason, I decide to re-write. Is there a gurantee in C++ standard such as : if no element be added/remove, no element would be moved? – Leon Jan 29 '19 at 07:17
  • @Leon - Yes, it's the iterator invalidation rules. So long as a vector's member function does not add/remove elements, it doesn't invalidate iterators. I.e. all the elements are still where you expect them to be. – StoryTeller - Unslander Monica Jan 29 '19 at 07:20

2 Answers2

0

I think the idea propsed by @AchimGuetlein is better.

Define as following:

vector<unique_ptr<ClassA> > container;

for (i = 0; i<number of queues; ++i)
    container.emplace_back(make_unique<ClassA>(args to constructor of ClassA));

instead of :

unique_ptr<ClassA [] > ques = make_unique<ClassA [] >(n, ...);

Although elements of vector might be moved, there is no moving occured to my queues. The objs moved just are unique_ptr self, but the addresses of the queues would never be changed.

Sorry for committing it as an answer, since the code sample can not be gracefully showed as codelet in a comment.

halfer
  • 19,824
  • 17
  • 99
  • 186
Leon
  • 1,489
  • 1
  • 12
  • 31
0

You don't have to use make_unique, you can construct the pointer and pass some manually allocated memory.

class ClassA {
 public:
  int a;
  float b;
};

const auto x = std::unique_ptr<ClassA[]>{new ClassA[2]{{1, 2}, {1, 2}}};
local-ninja
  • 1,198
  • 4
  • 11
  • Please conside such scenes as ClassPaire, unique_ptr> xy = XY(new X(), new Y()); If "new X()" is successful while "new Y()" failed, is there an oppotunity allow us to release the memory allocated by "new X()"? So, I aviod using "new" as possible as I can. – Leon Jan 29 '19 at 11:56
  • https://stackoverflow.com/questions/37514509/advantages-of-using-stdmake-unique-over-new-operator – Leon Jan 29 '19 at 11:58
  • there is a single `unique_ptr` and a single `new` in my example. therefore it's exception safe. you wanted to guard a single array. if you want to store additional `unique_ptr` _in_ the array, there is no reason why not to use `make_unique` in the initializer list. – local-ninja Jan 29 '19 at 13:31
  • Yes, there is only one "new" involked in this case. The method you proposed is good alse. Thanks a lot!!! – Leon Jan 30 '19 at 11:28