Boost logo

Boost Users :

Subject: Re: [Boost-users] [multi_array] Why the precondition on assignment?
From: alfC (alfredo.correa_at_[hidden])
Date: 2009-02-26 15:14:09


> With std::vector (and probably all containers?) operator= will
> potentially reallocate, so I don't understand why boost::multi_array
> should be special. It's not really a *surprise* reallocation is it?

first of all, linked list (~std::list), ordered trees (~std::set) and
queues (~std::queue) don't have this problem at all, and they only
need to allocate the storage for the new elements (or something of
order 1); and they are designed with that in mind.

going back to std::vector: What you say is correct for a dynamic (one
dimensional) arrays but std::vector implements a more complex
machinery to avoid reallocation in most cases. Something that
multi_array doesn't do at all.
In general, as std::vector grows (e.g. on push_back), it allocates
more space that it needs. This is done automatically each time the
vector *has* to grow, for example by duplicating the allocated
(reserved) space; or it can be done manually. That is why all these
methods are defined for std::vector

reserve()
capacity()

which are different from
resize()
size()

because of this trickery, reallocation in std::vector happens much
less ofter than you may think. The price is extra storage (or
optionally more manual control of reserved space.)
Going back to your example: If assigned and assignee std::vector are
of the "same order of size" then reallocation is unlikely, or can be
amortized the first assignment.

> operator= implies to me that you want to forget what's currently being
> held and assume a copy of the data that the other object has.
Don't get me wrong, I agree with you. I am just pointing at the
inconsistency in the design of multi_array but also trying to
understand what is the origin of the problem and think of possible
ways around them.

Now that you mentionad the example of std::vector. I am wondering
whether such manual control of multi_array reserved space is THE
solution.
something like

A.reserve({{shape1,shape2,shape3}}); // or just reserve
(shape1*shape2*shape3)

can the compromise solution for everyone. This can follow elegantly
the design of std::vector at least partially. Ronald?

(I would say automatic growing is a bad idea for multi_arrays, but
manually reserving space can't hurt). Even for the solution I gave in
my previous post I would need something like reserve because resize
actually does copies and/or constructs element, and I don't need that
because the elements will be overwritten anyway on the assignment.
That would be the my first application of reserve.

Regards,
Alfredo


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net