Modify the vector class in STL c++, is this possible? [duplicate] - c++

This question already has answers here:
C++ Erase vector element by value rather than by position? [duplicate]
(4 answers)
Closed 7 years ago.
I would like to modify a member function of the vector class. Is this possible? For example I would like to be able to delete with respect to value, and not the integer of the vector.

I think this does what you are looking for. This example removes all the occurrences of the number 6 from a vector using std::remove. xs.erase is to make sure the vector removes the elements and shrinks the vector to the new size.
I generally avoid modifying the STL containers as the people who implemented them are likely far smarter than me when it comes to this kind of thing. I recommend you learn the standard library algorithms, there generally is one suited to most kinds of general container operations.
#include <iostream>
#include <algorithm>
int main(int argc, char** argv)
{
std::vector<int> xs{1, 3, 6, 2, 6, 5};
std::cout << "xs size: " << xs.size() << std::endl; // xs.size() == 6
auto value_to_remove = 6;
xs.erase(std::remove(xs.begin(), xs.end(), value_to_remove), xs.end());
for (const auto& x : xs)
std::cout << x << ", ";
std::cout << std::endl; // 1, 3, 2, 5,
std::cout << "xs size: " << xs.size() << std::endl; // xs.size() == 4
return 0;
}
In this case, as with most other STL algorithms value_to_remove can be replaced with a (unary) lambda predicate opening up a whole world of exotic value finding.
You could wrap the above in a function as follows:
template <typename T>
void erase_by_value(std::vector<T>& xs, const T& value_to_remove)
{
xs.erase(std::remove(xs.begin(), xs.end(), value_to_remove), xs.end());
}

Related

Which method is to access Pairs? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
just to clear this doubt of fine i just want to ask that which method is faster or more efficient to access pairs while iterating over a contiguous block of pairs.
I used two method to iterate over a block.
1st
pair<int, char> arr[3] = {{1, 'a'}, {2, 'b'}, {3, 'c'}};
for (int i = 0; i < 3;i++){
cout << get<0>(arr[i]) << " " << get<1>(arr[i]) << endl;
}
2nd
for(const auto &x:arr){
cout << x.first << " " << x.second << endl;
get<0>(arr[0]);
}
which one is better and more efficient pls explain if u can.
You can compare them here: https://godbolt.org/z/4dPzKaPWr
As you will see, both have the same assembly code.
Efficiency takes many forms. I don't expect huge runtime differences in either case (you will have to measure/profile and expect std::cout to slow things down a lot, so be careful what you measure!).
But in terms of maintainability (which is also an efficiency).
I would use structured bindings on pairs (or not use pairs at all and use my own struct with clearly readable names)
#include <iostream>
#include <utility>
// don't use : using namespace std
struct my_data_t
{
int number;
char character;
};
int main()
{
std::pair<int, char> arr[]{{1, 'a'}, {2, 'b'}, {3, 'c'}};
my_data_t arr2[]{{1, 'a'}, {2, 'b'}, {3, 'c'}};
// using structured bindings for readabiliey
for(const auto& [number, character] : arr)
{
// for speed, don't use std::endl though
std::cout << number <<", " << character << "\n";
}
// or using own datastructure
for(const auto& entry : arr2)
{
std::cout << entry.number <<", " << entry.character << "\n";
}
return 0;
}
They are the same. The template arguments 0 and 1 in get<> must be compile-time constants, An implementation of get<>() refers to first or second for 0 or 1 respectively. The function call to get<>() gets inlined when optimized.

why std::move behaves like std::copy? [duplicate]

This question already has answers here:
Are std::move and std::copy identical?
(2 answers)
Closed 6 years ago.
Consider the following piece of code -
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> d {100, 200, 300};
std::vector<int> l {1, 2, 3, 4, 5};
std::move(d.begin(), d.end(), std::inserter(l, l.begin()));
for (int n : l) std::cout << n << ' ';
std::cout << '\n';
for (int n : d) std::cout << n << ' ';
std::cout << '\n\n';
for (int &n : d) n +=5;
for (int n : l) std::cout << n << ' ';
std::cout << '\n';
for (int n : d) std::cout << n << ' ';
std::cout << '\n';
}
Here the original std::vector l was inserted with contents of std::vector d after the move operation. I know that all standard library objects that have been moved from are placed in a valid but unspecified state, however, I was curious to move further and inspect the values. The value of std::vector d still remained same after the move operation which could be justified as if both are referring to same data location? Again, when I tried to modify those values, the change is not reflected back in the new std::vector l container.
Here's the output -
100 200 300 1 2 3 4 5
100 200 300
100 200 300 1 2 3 4 5
105 205 305
It seems the values are copied from source container to destination container and the source container gets to keep originals. Doesn't this sound like a std::copy operation?
For plain old data, moving and copying are identical. There's no way to move ordinary data other than by copying. Things are different if, for example, you have ownership of some other object that can be transferred without copying it (like std::string or std::shared_ptr has). But for int, that doesn't apply.

C++ STL vector Deep erase

How to deep erase a vector?
Consider the following code.
#include<algorithm>
#include<iostream>
#include<iterator>
#include<vector>
using namespace std;
int main(){
vector<int> v {1,2,3,4,5};
for_each(begin(v),end(v),[&v](int& n){
static auto i = (int)0;
if(n == 2){
v.erase ( begin(v) +2, end(v));
}
cout << n << " having index " << i++ << endl;
});
v.erase ( begin(v) +2, end(v));
cout << v.size() << endl << v[4] << endl;
}
Output is
1 having index 0
2 having index 1
3 having index 2
4 having index 3
5 having index 4
2
4
What I want is accessing v[i] for any i from 2 to 4 to be invalid and compiler to throw an error.
In simpler words how to deep erase a vector?
You're triggering undefined behavior and therefore your results cannot be trusted.
If you need to check for boundaries use std::vector::at
vector<int> v{ 1,2,3,4,5 };
v.erase(begin(v) + 2, end(v));
try {
auto val = v.at(4);
} catch (std::out_of_range&) {
cout << "out of range";
}
Unless you code your own facility or workaround, you can't have such compile-time checks with std::vector. More information and some suggestions here: https://stackoverflow.com/a/32660677/1938163
I do not have time right now to give examples, but the only way I can think to cleanly do this is to either make a custom class to wrap or subclass vector. You could then produce a custom [] and at operators which throw an error on certain indexes. You could even have a deletion method which adds indeces to this list of banned ones.
Now if you need the error at compile time this is harder. I think something might be possible using a constexpr access operator and some static_asserts but I am not confident exactly how off hand.

Individual elements in a std::vector [C++]

What's the best way to select individual elements from a C++ std::vector?
I'm used to C-style arrays and this is the first time I'm using vectors.
I'm looking for something like:
std::vector<std::string> myvector;
astring = myvector[1];
bstring = myvector[3];
cstring = myvector[10];
And so on.
There are several ways to access elements in a std::vector:
myVector[3] - access the 4th element (0-indexed).
myVector.at(3) - access the 4th element with bounds checking. Throws an exception if the index is not less than the number of elements.
iterating over all elements with the standard algorithms: std::find(std::begin(myVector), std::end(myVector), 10).
Personally I've never found a use for at(), since I keep track of the index that I'm using anyway. I rarely just take a number from somewhere and stick it into [].
But be aware that accessing an index not less than the number of elements using [] is Undefined Behaviour (if the vector has 4 elements, you access them with 0, 1, 2, and 3). You are expected to be sure it is safe yourself. So in your example, this would be illegal, since you don't put anything into the vector first.
You ask for the best way... The answer is: There is no general best way
The best way is not always the same. It really depends on what your code is doing.
The best way also depends on what you want to achieve, e.g. best performance, best code maintainability, best code readability and so on.
The best way is also based on a personal view.
So just to repeat the answer: There is no general best way
Other answers mentions a number of different posibilities. I'll add one more.
// To iterate over all elements in a vector you can do
for (auto& e : someVector)
{
// Do something with e, e.g. print it
cout << e;
}
There are three general ways to access elements of a vector.
The first one is similar to accessing elements of an array using the subscript operator [].
For example
std::vector<std::string> v = { "Hello", "World" };
std::cout << v[0] << ' ' << v[1] << std::endl;
The second one is to use iterators similar to using pointers. For example
std::vector<std::string> v = { "Hello", "World" };
auto it = v.begin();
std::cout << *it << ' ' << *( it + 1 ) << std::endl;
The third one is to use member function at that checks the boundaries of a vector and throws an exception when an attempt is made to access memory beyond the vector
std::vector<std::string> v = { "Hello", "World" };
std::cout << v.at( 0 ) << ' ' << v.at( 1 ) << std::endl;
Also there are methods to acess the first and the last elements of a vector
for example
std::vector<std::string> v = { "Hello", "World" };
std::cout << v.front() << ' ' << v.back() << std::endl;
To access sequentially all elements of a vector you can use three kinds of loops.
For example
std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
or
std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for ( std::vector<int>::size_type i = 0; i < v.size(); i++ ) std::cout << v[i] << ' ';
std::cout << std::endl;
or
std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for ( auto it = v.begin(); it != v.end(); ++it ) std::cout << *it << ' ';
std::cout << std::endl;
Simple use operator[] as you do with arrays. If you want boundary checking use at().
That is generally how you access vectors, they were made to be similar to arrays using the indexing operator.
However, once you when you declare a vector like you do, without passing any arguments to the constructor the vector is empty, which means that any indexing will be out of bounds and you will have undefined behavior.
If you want to specify an initial size, you could pass an argument to the constructor:
std::vector<std::string> myvector(11); // Creates a vector of 11 elements
If you never will change the size of the vector, if the size is fixed at the time of compilation using a compile-time constant, then you should probably be suing std::array instead:
std::array<std::string, 11> myarray;
You can access (i.e. select some element) a std::vector similar to C-style arrays i.e. by using indexes. Similar to arrays, no bound checking is performed in case of std::vector as well when you access some element which is not present. For example, you have inserted 10 elements in vector v but accessing 200th element using v[200] - but it could result undefined behavior, so be careful.

Which C++ STL container provides `extract_max()`, `find(element_value)` and `modify(element)` functionality?

I want to use a C++ STL container to implement Prim's algorithm. I need extract_max, find(element) and modify(element_value) functionality, but std::priority_queue only provides extract_max. Is there some other container that I can use? Obviously I want all of these to be as fast as possible.
Edit: The container should also provide functionality to modify the value of its element.
Push your elements in an std::set<T, std::greater<T>>, which is an ordered heap.
Call *set::begin() to get to the max element on O(1) or O(log(n)), depending on how set::begin() is implemented.
Use set::find to perform a search in O(log(n)).
To modify an element, you must unfortunately remove it from the set and then insert the modified version. (This also applies to make_heap and friends). There could exist an answer where this is not necessary, but (A) you'd have to be paranoid about what members are used for comparison vs equality, and (B) the difference in speed is very small. So there is no common container that works that way.
If the element ordering is not unique in it's ordering, use std::multiset instead, which is otherwise identical.
Example:
#include <iostream>
#include <set>
int main()
{
std::set<int, std::greater<int>> v { 3, 1, 4, 1, 5, 9 };
std::cout << "initially, v: ";
for (auto i : v) std::cout << i << ' ';
std::cout << '\n';
auto largest = *v.begin();
v.erase(v.begin());
std::cout << "largest element: " << largest << '\n';
std::cout << "after removing the largest element, v: ";
for (auto i : v) std::cout << i << ' ';
std::cout << '\n';
}
Live demo