I'm trying to make a remove function for an array class that uses an array of pointers to store objects.
So what I've got is a list of pointers to objects declared like so:
objname* list = new objname[100];
Note, its declared as a member of a class, lets call it myClass.
What I want is to make a function to myClass that takes an index as a parameter, and removes the object from list on that index. Here's what I've got and what I want to do.
void myClass::remove(int index)
{
objname* temp = new objname[listlen]; //creating a temporary list to copy values from the "main" list.
//want to copy elements from 0 to index in "this->list" and store inside temp, then skip one element and copy the rest.
}
There might be a better way to get this functionality and if so I'm open to suggestions.
What I want is to make a function to myClass that takes an index as a parameter, and removes the object from list on that index.
You can do this easily with an std::vector and std::next:
#include <vector> // for std::vector
#include <iterator> // for std::next
std::vector<objname> v;
void myClass::remove(int index)
{
v.erase(std::next(v.begin(), index));
}
Obviously you should first check that the vector is large enough for index.
But if what you really want to do is copy a portion of one array into another, again, you can easily do this with standard library components:
std::vector<objname> v = ...;
std::vector<objname> temp(v.begin(), std::next(v.begin(), index));
Here, temp will contain copies of the first index elements of v.
If you use arrays and are not yet allowed to use std::vector then you can do the task by applying two times standard algorithm std::copy
For example, (I suppose that listlen is the size of the original array)
#include <algorithm>
//...
objname* temp = new objname[listlen - 1];
std::copy( std::next( list + index ), list + listlen,
std::copy( list, list + index, temp ) );
Expression std::next( list + index ) can be substituted for list + index + 1 provided that for the both expressions index is less than listlen.
Related
If I emplace an element into a std::vector by using emplace or emplace_back, the element will be constructed without needing an operator=.
Now I already have a std::vector with elements, and I want to set an element at an index to a new value. This is my current solution, a new solution should behave the same:
std::vector<Type> vec;
// ... fill the vector
for (int value = 0; value <= 10; ++value)
vec.emplace_back( Type(value) );
// replace at index
int index = 5;
Type newelement {30};
vec.erase( vec.begin() + i );
vec.insert( vec.begin() + i, newelement );
But I obviously don't want to do just that, as that moves all the other elements in the std::vector around, which makes an O(1) complexity task take O(n) time.
Edit:
I changed the code snipped to use insert, which is how it actually is in my current code. I now realize that I am confused by not knowing the difference between insert and emplace. Maybe clarifying that would answer this question, too.
I think you can just use vec[index] = Type(30); which uses move assignment because the new element is temporary. You need move assignment anyway for std::erase.
If for some reason you want to name the temporary element, you could instead use vec[index] = std::move(newelement);.
The code
vec.erase( vec.begin() + i );
vec.insert( vec.begin() + i, newelement );
can be replaced with
std::swap( vec.at( i ), newelement );
This method will not shift the contents of the vector.
Please feel free to edit this answer to show if and how this method differs apart from not shifting the vector contents.
First of all, your example is not correct since you should pass just the arguments of Type's constructor to emplace_back, not a full object. Your loop would look like this
std::vector<Type> vec;
for (int value = 0; value <= 10; ++value)
vec.emplace_back(value);
Then, according to cppreference, when using emplace there is no need to call erase first if an element already exists at the requested position.
The element is constructed through std::allocator_traits::construct,
which typically uses placement-new to construct the element in-place
at a location provided by the container. However, if the required
location has been occupied by an existing element, the inserted
element is constructed at another location at first, and then move
assigned into the required location.
Something like this
// replace at index
int index = 5;
vec.emplace( vec.begin() + index, 30);
constructs an object at the desired position with a better complexity than calling erase first.
I have allocated two arrays in the memory using pointers and I also have a function to get the user's input of elements and store it in the arrays. My only problem is I do not know how to find the common element(s) in the two arrays and store it in another new array. How do I do it?
I have already tried comparing each element of the first array to each of the elements of the second array, and if they are equal to each other, then I should store it in the new array. But still, this does not seem for me an efficient code.
int *j = new int[n];
getList(j, n);
int *k = new int[m];
getList(k, m);
/* how would I create a new array to
store the common elements of the
previous two arrays and display its elements? */
You certainly want to use std::set_intersection from the <algorithm> header for this. Remember that raw pointers to contiguous memory qualify as input iterators, hence:
#include <algorithm>
#include <vector>
std::vector<int> result;
// Make sure that [j, j + n) and [k, k + m) are sorted
std::set_intersection(j, j + n, k, k + m, std::back_inserter(result));
Note that as #john pointed out in the comments, this algorithm requires that both input sequences are sorted.
If the input ranges aren't sorted anyway and you're worried about performance, you might want to read this blog post for an alternative.
I have a list like:
list <char>mylist
I give it some elements
for (int i = 0; i < 10; i++)
{
mylist.push_back(i);
}
My questtion is that if there is anyway to copy those elements from list to an array like
char A[10];
static array
or
char *A= new char[10];
dynamic array
is that if there is anyway to copy those elements from list to an array
Yes, there is a way to copy objects from a container to another. You can use the following algorithm:
get output iterator to the output container
get input iterator to first element of the input container
while input iterator does not point to the end
dereference the iterator to get a reference to the element
dereference the output iterator, and copy assign the element
increment both iterators
You don't need to write the loop yourself though because standard library already has done it for you: std::copy.
I would like to overwrite an item pointed by index even if that index doesn't exist yet. operator[] works up until it is not out of bound. emplace seems to do this, but it need an iterator for the first param. I could use myvector.begin()+index but it's invalid when the vector is empty.
Clarification. My current implementation:
while (index < myvector.size())
myvector.push_back("");
myvector[index] = val;
I was hoping for an std method. The array is always very small (few elements).
Using the accepted answer, my code changes to:
if (index >= myvector.size()) // to avoid destroying the remaining elements when the index is smaller than current size
myvector.resize(index+1);
myvector[index] = val;
To overwrite an element of given index, that index must be inside valid vector bounds.
You can set the size of your vector to whatever value using vector::resize, and just use operator[] with indexes in the range [0, size-1]:
std::vector<std::string> data;
...
data.resize(100);
// Use data[i] for i = 0,1,2,...99
I ran into this problem when I tried to write out an new algorithm to reorder elements in std::vector. The basic idea is that I have std::list of pointters pointing into std::vector in such way that *list.begin() == vector[0], *(++list.begin()) == vector[1] and so on.
However, any modifications on list's element positions breaks the mapping. (Including appended pointers) When the mapping is broken the list's elements can be in random order but they point still into correct elements on vector. The task would be to reorder the elements in vector to correct the mapping.
Simplest method to do it (How I have done it now):
create new empty std::vector and resize it to equal size of the old vector.
iterate through the list and read elements from the old vector and write them into new vector. Set the pointer to point into new vector's element.
swap vectors and release the old vector.
Sadly the method is only useful when I need more capacity on the vector. It's inefficient when the current vector holding the elements has enough capacity to store all incoming elements. Appended pointers on the list will point into diffrent vector's storgate. The simple method works for this because it only reads from the pointers.
So I would want to reorder the vector "in place" using constant amount of memory. Any pointer that was not pointing into current vector's storgate are moved to point into current vector's storgate. Elements are simple structures. (PODs)
I'll try post an example code when I have time..
What should I do to achieve this? I have the basic idea done, but I'm not sure if it is even possible to do the reordering with constant amount of memory.
PS: I'm sorry for the (possibly) bad grammar and typos in the post. I hope it's still readable. :)
First off, why do you have a list of pointers? You might as well keep indices into the vector, which you can compute as std::distance(&v[0], *list_iter). So, let's build a vector of indices first, but you can easily adapt that to use your list directly:
std::vector<T> v; // your data
std::list<T*> perm_list; // your given permutation list
std::vector<size_t> perms;
perms.reserve(v.size());
for (std::list<T*>::const_iterator it = perm_list.begin(), end = perm_list.end(); it != end; ++it)
{
perms.push_back(std::distance(&v[0], *it));
}
(There's probably a way to use std::transform and std::bind, or lambdas, to do this in one line.)
Now to do the work. We simply use the cycle-decomposition of the permutation, and we modify the perms vector as we go along:
std::set<size_t> done;
for (size_t i = 0; i < perms.size(); while(done.count(++i)) {})
{
T tmp1 = v[i];
for (size_t j = perms[i]; j != i; j = perms[j])
{
T tmp2 = v[j];
v[j] = tmp1;
tmp1 = tmp2;
done.insert(j);
}
v[i] = tmp1;
}
I'm using the auxiliary set done to track which indices have already been permuted. In C++0x you would add std::move everywhere to make this work with movable containers.