[Iterator] shared_container_iterator usability
Hello boosters, a design question: how often (if ever) and under which circumstances do you use shared_container_iterator? (http://www.boost.org/doc/libs/1_49_0/libs/utility/shared_container_iterator....) I don't feel too good about allocating a vector<> on the heap but I guess it was made for some reason and motivated by actuall need. What are good use cases for such iterator? Obviously returning a container from function (as presented in example) is not one of them. Cheers, Simon
On 19.3.2012 16:43, Szymon Gatner wrote:
Hello boosters,
a design question: how often (if ever) and under which circumstances do you use shared_container_iterator?
(http://www.boost.org/doc/libs/1_49_0/libs/utility/shared_container_iterator....)
I don't feel too good about allocating a vector<> on the heap but I guess it was made for some reason and motivated by actuall need. What are good use cases for such iterator? Obviously returning a container from function (as presented in example) is not one of them.
Erm, why wouldn't it be a good idea? That put aside, shared_container_iterator comes handy when you need to return several values that are eg. picked up from a larger pool and/or otherwise modified (and thus can't directly return iterators as the contents needs to be allocated). You don't want to return a copy of vector and perhaps don't want to pass as an argument a target vector either. Having a local copy (that would be returned as a reference) isn't thread safe, so that one is one is kinda bad, too. Moreover, as vector is returned wrapped inside a shared_container_iterator (well, a pair of those) one may pass it directly to Boost.Range or Boost.Foreach (yep, std::pair supported) without spending too much time thinking when and how to allocate and release memory as shared_ptr does that for you. I don't really know why you should feel bad about allocating a vector from heap as std::allocator will use heap anyway. Not really seeing that operating vector from stack and it's contents from heap would be any faster than having the both allocated from heap. If I'd had to optimize (as in Optimize, not some needless micro optimizations) some vector / array related operation, I think I'd forget any std container, let alone shared_ptr, in the first place... -- Pekka
Erm, why wouldn't it be a good idea?
Because one would normally just return a function-local vector by value which is much cheaper (with move semantics) then heap allocation of a container + 2 x shared_ptr construction.
Moreover, as vector is returned wrapped inside a shared_container_iterator (well, a pair of those) one may pass it directly to Boost.Range or Boost.Foreach (yep, std::pair supported) without spending too much time thinking when and how to allocate and release memory as shared_ptr does that for you.
All well supported also with just returning a container by value.
I don't really know why you should feel bad about allocating a vector from heap as std::allocator will use heap anyway.
This way you get 2 heap allocations + shared_ptr<> construction as opposed to just internal allocation of vector (using allocator). This is especially bad if returned vector turns out to be empty. In that case vector might not do allocation at all so vector creation and return are practically free.
If I'd had to optimize (as in Optimize, not some needless micro optimizations) some vector / array related operation, I think I'd forget any std container, let alone shared_ptr, in the first place...
Interesting. What would you use instead of a vector + specfic allocator when "Optimizing"? Continuous block of memory is rather hard to beat in terms of data processing speed. Anyway, still not convinced of good use case ;) Is there any? Cheers
On 19.3.2012 18:28, Szymon Gatner wrote:
Erm, why wouldn't it be a good idea?
Because one would normally just return a function-local vector by value which is much cheaper (with move semantics) then heap allocation of a container + 2 x shared_ptr construction.
Moreover, as vector is returned wrapped inside a shared_container_iterator (well, a pair of those) one may pass it directly to Boost.Range or Boost.Foreach (yep, std::pair supported) without spending too much time thinking when and how to allocate and release memory as shared_ptr does that for you.
All well supported also with just returning a container by value.
I don't really know why you should feel bad about allocating a vector from heap as std::allocator will use heap anyway.
This way you get 2 heap allocations + shared_ptr<> construction as opposed to just internal allocation of vector (using allocator). This is especially bad if returned vector turns out to be empty. In that case vector might not do allocation at all so vector creation and return are practically free.
Well, obviously if your compiler has good and guaranteed move semantics along with return value optimizations and you're extermely speed oriented in every way, that's your way to go. You don't have to use everything that library has to offer to you :) The same goes with every choice, whether to use raw pointers (fast, but possibly allocation troubles) or some smart pointer (a small speed penalty, but carefree usage) etc.; It all depends. I must say, that personally I'm not really into returning anything except pod types and trivial things by value. Naturally it happens, strings for an example. Nevertheless, I think it's meaningless to operate on such a low level where you calculate each and every one of your allocations and construtions in a place that they don't usally really matter. (Say, you do a million operations per function call - The first place to look for improvement wouldn't be the few constructions outside the actual and heavyweight loop.) Naturally, if your vector contains only a dozen values the return type is a good question. On the other hand, it's again meaningless if you call your function a couple of times. How about if you call it a million times? I think a small refactoring could be in place etc. I think you get what I mean ;-)
If I'd had to optimize (as in Optimize, not some needless micro optimizations) some vector / array related operation, I think I'd forget any std container, let alone shared_ptr, in the first place...
Interesting. What would you use instead of a vector + specfic allocator when "Optimizing"? Continuous block of memory is rather hard to beat in terms of data processing speed.
Well, I suppose as vectors are pretty much guaranteed to have a contiguous memory allocation and if your platform and compiler is able to use hardware speedups it could work; especially DSP platforms have many loop related tricks that allow certain things to be executed in parallel + the usual (unrolling etc.) tricks. However, this gets too much off the track here. So, my answer final answer is to not use things just because they exist but only if they provide something that is useful for you. What works for me might not work for you as seen here.. -- Pekka
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi! Am 19.03.12 17:28, schrieb Szymon Gatner:
This way you get 2 heap allocations + shared_ptr<> construction as opposed to just internal allocation of vector (using allocator). This is especially bad if returned vector turns out to be empty. In that case vector might not do allocation at all so vector creation and return are practically free.
The shared_ptr construction means what? The vector will allocate and the boost::make_shared allocates memory on the heap. The copying of the shared_ptr is rather cheap in comparison. One use case: distribute any number of subranges of a shared range. Imagine a function that returns (by value) a list (or vector) of substrings (shared_iterator pairs = ranges) of some larger string. The substrings can shared ownership on the underlying large string. Of course there are alternatives to shared iterators, but its a valid use case anyway, I think. Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG/MacGPG2 v2.0.17 (Darwin) Comment: GPGTools - http://gpgtools.org Comment: keyserver x-hkp://pool.sks-keyservers.net iEYEARECAAYFAk9nrsoACgkQhAOUmAZhnmp1igCeP7UeAho8Hc1Q8iQy4x/LOXu9 FYEAnRtyEGOqhEfnRrXWkFG4D3HOsmyY =bodr -----END PGP SIGNATURE-----
participants (3)
-
Frank Birbacher
-
Pekka Seppänen
-
Szymon Gatner