C++ STL vector for existing data - c++

Can I create an std::vector using my pre-existing data instead of it allocating new memory and copying the data?
To be clearer, if I have a memory area (either a c-array or part of another vector or whatever) and I want to provide vector-like access to it, can I create a vector and tell it to use this block of memory?

No, but you could write your own class that does this. Since this would be a fairly common need I wouldn't be surprised if someone else has done this already.
However the normal C++ way would be to write template code to operate on iterators. You can create iterators for any portion of a vector, or for any portion of a C array (and much else). So writing template code for iterators is probably what you should be doing.

Since you can use a custom allocator when creating a vector, it is technically possible.
However, I wouldn't recommend it. I'd just create a vector with a fixed size (apparently you can get a hold of that) and then use std::copy.

Algorithms which iterate over a container accept a pair of iterators which define the input range. You can use the algorithm with iterators which point to a middle of a big container.
Examples:
std::vector<int> big_vector(100000);
// initialize it
//...
std::sort(big_vector.begin()+100, big_vector.begin()+200); // sort a subrange
int big_array[100000]; //c-style array
// initialize it
//...
std::sort(std::begin(big_array)+300, std::begin(big_array)+400); // sort a subrange

From C++20 we have std::span which provides the exact same thing you are looking for. Take a look at https://en.cppreference.com/w/cpp/container/span.

Related

Sharing an array with STL vectors

I would like to share the contents of an array of doubles a of size k with one or more STL vectors v1, v2...vn.
The effect that I want from this shared storage is that if the underlying array gets modified the change can be observed from all the vectors that share its contents with the array.
I can do that by defining the vectors v1...vn as vectors of pointers
vector<double*> v1;
and copy the pointers a to a + k into this vector. However, I do not like that solution. I want the vectors to be a vector of doubles.
Given that you can extract the underlying pointer from a vector I am assuming one could initialize a vector with an array in such a way that the contents are shared. Would appreciate help about how to do this.
Given that you can extract the underlying pointer from a vector I am assuming one could initialize a vector with an array in such a way that the contents are shared.
No, you can't do this. The Standard Library containers always manage their own memory.
Your best option is to create the std::vector<double> and then use it as an array where you need to do so (via &v[0], assuming the vector is non-empty).
If you just want to have the container interface, consider using std::array (or boost::array or std::tr1::array) or writing your own container interface to encapsulate the array.
This sounds to me like you want to alias the array with a vector. So logically you want a vector of references (which doesn't work for syntactical reasons). If you really really need this feature, you can write your own ref wrapper class, that behaves exactly like an actual C++ reference, so the users of your vn vectors wont be able to distinguish between vector<T> and vector<ref<T> > (e.g. with T = double). But internally, you could link the items in the vectors to the items in your "master" array.
But you should have darned good reasons to do this overhead circus :)
OK, Standard Library containers are both holders of information, and enumerators for those elements. That is, roughly any container can be used in almost any algorithm, and at least, you can go through them using begin() and end().
When you separate both (element holding and element enumeration), as in your case, you may consider boost.range. boost.range gives you a pair of iterators that delimit the extent to which algorithms will be applied, and you have the actual memory store in your array. This works mostly to read-access them, because normally, modifying the structure of the vector will invalidate the iterators. You can recreate them, though.
To answer your question, as far as I know std::vector can not be given an already constructed array to use. I can not even think how that could be done since there are also the size/capacity related variables. You can possibly try to hack a way to do it using a custom allocator but I feel it will be ugly, error prone and not intuitive for future maintenance.
That said, if I may rephrase your words a bit, you are asking for multiple references to the same std::vector. I would either do just that or maybe consider using a shared_ptr to a vector.

C++ Fixed size container with swappable elements

I'm searching for a container with the following functionality:
Fixed size at runtime. Thus, memory shouldn't be allocated in little chunks (like std::list does).
Elements should be swappable (Something like std::list::splice offers).
EDIT:
Thinking of a list: I just need to move elements from an arbitrary position to the front.
EDIT2:
I would like to use something like a std::list, but takes advantage of a runtime fixed size.
I'd think of TR1 array:
std::array<T, int>
Or, if you haven't got that yet,
boost::array<T, int>
Which is identical for all intents and purposes. Of course the validity of std::swap on elements depends on availability of proper copy constructor/assignment operator.
It's not too clear to me what you are looking for. Two solutions come to mind: std::vector (created with the maximum size), coupled with a good implementation of swap for your objects, or a custom allocator for std::list, which pre-allocates the number of nodes you'll need in a single block.
You can specify the (initial) size of an std::list at construction time :
std::list<Type> myList = std::list<Type>(10);
You can still grow/shrink it afterwards, but the list will contain 10 default constructed Type objects from the start.
Does that suit your needs ?
std::vector ?
Array based. Can specify the size and has a swap function.
You haven't said what you'll be using it for so I don't really know if you're going to have any speed issues with it.

Reference to a subset of a container object

i have a quick question about having a reference to a subset of a collection.
Consider i have a vector of objects. Now I want to create another vector which is a subset of this vector, and I dont want to create a copy of the subset of objects.
One of the ways I was thinking about is creating a vector<auto_ptr<MyClass> >. Is this a good approach?
Please suggest if you think any other containers or idioms or patterns would help in this case.
Thank you
No ! See : Why it is wrong to use std::auto_ptr<> with STL containers ?
Now, as an alternative, you could store raw pointers or boost::shared_ptr depending on your needs.
Another, possibly more STL way would be to just have the one vector but keep track of sub ranges using pairs of iterators (note all the algorithms use iterators for exactly this reason)
You can use a vector of indices: vector<int> (or vector<size_t> if you want to be pedantic). This is better than storing pointers (pointers in a general meaning: raw C/C++ pointers, shared_ptr, iterator, etc) if the containing vector is not constant.
Consider the following scenario: the "big" vector contains an apple, an orange and a lemon, while the "small" vector contains a pointer to the apple. If you add a bunch of other fruits to the big vector, the STL is going to reallocate storage for the vector, so the pointer to the apple will be invalid (point to deallocated memory).
If the above scenario is possible, use a vector of indices. If it is not possible, use the other techniques (e.g. a vector of raw pointers, or a vector of copies of the objects).
If the subsection is contiguous you can reference the subsection using an iterator and a count indicating how many items you are referencing.
The sane way to do this would be to create some sort of templated class which you could construct with a container reference and two indices, and let the class do all the bounds and error checking, though I'm unsure how you'd be able to tell if the underlying container still existed at some later time...

set vs vector with custom iterator

I understand this question may be quickly flagged as a duplicate of many other more popular questions, but I'll still ask it:
I need a container that provides duplicate checking on insert (like std::set, but allows me to modify elements already present (like std::vector). It should also be relatively fast to search for elements (which would prefer std::set again). Would it be better to use a vector and perhaps a custom duplicate-checking insert_iterator instead of modifying set elements by erasing and reinserting them?
Thanks
What is to stop you from using a std::set? If you need to modify an element, copy it, erase it, then re-insert.
Have you looked into using a map?
Reference
A map may be a good solution to your problem.
If your strings are long and performance is critical then you may be stuck with a custom container that wraps something like a parallel vector<string> and set<string *>. Provide a custom comparator for the set so that it dereferences through the pointer to make the comparisons. To modify an element, remove the pointer from the set, modify the string, then reinsert the pointer.
This get a bit messy when you want to remove container elements, so you would want to use some form of lazy deletion. At that point you are very close to a full-blown free-object pool for your strings.
If you're using a vector of strings in performance-critical code, then watch out for the vector reallocations which would manually copy each string into the new memory chunk. You can bypass that by watching for an upcoming reallocation, creating a new vector of empty strings (pre-reserved to double size), and then using string::swap on each element to move the old data into the new larger vector.
Things will be much nicer when c++0x move semantics are widely available.

What is the C++ equivalent of C# Collection<T> and how do you use it?

I have the need to store a list/collection/array of dynamically created objects of a certain base type in C++ (and I'm new to C++). In C# I'd use a generic collection, what do I use in C++?
I know I can use an array:
SomeBase* _anArrayOfBase = new SomeBase[max];
But I don't get anything 'for free' with this - in other words, I can't iterate over it, it doesn't expand automatically and so on.
So what other options are there?
Thanks
There is std::vector which is a wrapper around an array, but it can expand and will do automatically. However, it is a very expensive operation, so if you are going to do a lot of insertion or removal operations, don't use a vector. (You can use the reserve function, to reserve a certain amount of space)
std::list is a linked list, which has far faster insertion and removal times, but iteration is slower as the values are not stored in contiguous memory, which means that address calculation is far more complex and you can't take advantage of the processors cache when iterating over the list.
The major upside compared to the vector or deque is that elements can be added or removed from anywhere in the list fairly cheaply.
As a compromise, there is std::deque, which externally works in a similar way to a vector, but internally they are very different. The deque's storage doesn't have to be contiguous, so it can be divided up into blocks, meaning that when the deque grows, it doesn't have to reallocate the storage space for its entire contents. Access is slightly slower and you can't do pointer arithmetic to get an element.
You should use a vector.
#include <vector>
int main()
{
std::vector<SomeBase*> baseVector;
baseVector.push_back(new SomeBase());
}
C++ contains a collection of data containers within the STL.
Check it out here.
You should use one of the containers
std::vector<SomeBase>
std::list<SomeBase>
and if you really need dynamically allocated objects
std::vector<boost::shared_ptr<SomeBase>>
std::list<boost::shared_ptr<SomeBase>>
Everyone has mentioned that the common SC++L controls, but there is another important caveat when doing this in C++ (that Chaoz has included in his example).
In C++, your collection will need to be templated on SomeBase*, not on SomeBase. If you try to assign an instance of the derived type to an instance of the base typem you will end up causing what is called object slicing. This is almost definately not what you are trying to do.
Since you are coming from C#, just remember that "SomeBase MyInstance" means something very different in both languages. The C++ equivalent to this is usually "SomeBase* MyPointer" or "SomeBase& MyReference".
Use a vector. Have a look here.
I am a huge fan of std::deque. If you want things for free, the deque gives them to you. Fast access from the head and tail of the list. iterators, reverse_iterators, fast insertion at the head and the tail. It's not super specialized, but you wanted free stuff. ;-)
Also, I will link a great STL reference. The STL is where you get all the standard "free" stuff in C++. Standard Template Library. Enjoy!
Use STL. std::vector and std::set for instance. Plenty of examples out there.