Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
all
I am using vector in C++ STL to store my data. I pass and return them into and from functions. However, as the data size grows, the program is slower and slower. Thus I am updating the codes to an "iterator version".
What I want to archieve is that use iterators to pass, return and iterate STL vectors.
I am now ok with the operations with 1-dimensional vector, just like manipulating the arrays. However, when it comes to 2-dimensional vector, I am a bit confused.
Can anyone show me a simple code example that how to iterate a 2D vector using STL iterator?
Many thanks in advance.
Regards
Long
You state that your basic problem is performance, right?
You assume that this is caused due to copying.
Perhaps there could be simpler solutions for your problem:
Check if vectors can be passed by (const) reference
Check if shared_ptr makes sense
Consider if move semantics can help
Perhaps compiler version or implementation prevent return value optimization
If you need to know the size of a vector, and have two iterators it1 it2,
std::distance(it1, it2);
will tell you the distance between them. This will happen to be the size if they are begin and end
If you have a function like
int work(std::vector<int> items)
{
//...
}
this copies the vector items, so will use more RAM and take longer.
Sending a const ref instead will not copy the vector. Making it const stops you changing it, which might not help you, but you haven't posted any code so I don't know what you want to do.
int work(const std::vector<int> & items)
{
//...
}
Well its already somewhere on stackoverflow
But if you don't want to search here it is :
std::vector<std::vector<int> > vec{ {1,2,3},{4,5,6}};
//Simplest Way:- (C++11)
for(auto row:vec)
{
for(auto col:row)
std::cout<<col<< " ";
std::cout<<std::endl;
}
//OR Using iterator
std::vector<std::vector<int> >::iterator r;
std::vector<int>::iterator c;
for (r = vec.begin(); r != vec.end(); r++) {
for (c = r->begin(); c != r->end(); c++) {
std::cout<<*c<< " ";
}
std::cout<<std::endl;
}
Can get distance only between two iterators of same container
std::vector<int>::iterator s = v2.begin(); //Can be any start
std::vector<int>::iterator e = v2.end(); // Can be any end
std::cout<<"Distance :"<<std::distance(s,e)<<std::endl;
Related
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.
This post was edited and submitted for review 7 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
for (auto& i : just_a_vec )
Or an iterator for loop.
for (std::vector<std::string>::iterator it = just_a_vec.begin(); it < just_a_vec.end(); it++)
Iterators predate range-based for loops, so they used to be the only of these two alternatives available. Nowadays, range-based for has mostly replaced iterators when dealing with a simple loop.
However, iterators can be used in various other contexts as well. For example, you can do std::sort(v.begin(), std::next(v.begin(), 5)) to sort the first five elements of a vector while leaving the rest of it alone.
Going back to iterating over a whole container:
If you can accomplish what you want with a range-based for, then it leads to more legible code, so they are preferable by default.
If you need iterators for some reason, such as using an algorithm that requires them, or because you need to jump ahead or back while iterating, then use those instead.
Also: In the later case, you can/should still use auto when declaring the iterator:
for(auto it = just_a_vec.begin(); it < just_a_vec.end(); it++) {
}
Edit: as asked: here's a simple, if a bit contrived, example where an iterator-based loop can still be useful:
// adds all values in the vector, but skips over twos values when encountering a 0
// e.g.: {1,2,0,4,5,2} => 5
int my_weird_accum(const std::vector<int>& data) {
int result = 0;
for(auto it = data.begin(); it != data.end(); ++it) {
auto v = *it;
result += v;
if(v == 0) {
// skip over the next two
assert(std::distance(it, data.end()) > 2);
std::advance(it, 2);
}
}
return 0;
}
Quick personal answer: Its somewhat sylistic and based on what version of c++ you are using. I typically prefer range based, but there are certainly moments iterators shine as well. Add both to your toolchest. For further reading.
Here is a list of other SO answers that get more into the performance and use cases.
What's the difference between iterator syntax in range-based loops for STL containers
Is the ranged based for loop beneficial to performance?
range based for loop vs regular iterator for loop
For further information. Google
Range vs iterator loop c++
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am attempting to solve the interview problem from leet code to remove duplicates from a vector of ints.
Below is my my code for the answer:
#include <vector>
#include <set>
using namespace std;
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
vector<int>::iterator itr;
set<int> temp;
for (itr = nums.begin(); itr != nums.end(); itr++) {
if (temp.insert(*itr).second == false) {
nums.erase(itr);
}
}
return nums.size();
}
};
I've added includes for completion.
The problem I've run into is if I have an input vector as so [0,0,1,1,2,2,3,3,4,4,5,5] my function will only erase the duplicates that are not 1 or 2.
Thus my answer will be [0,1,1,2,2,3,4,5]. My understanding is that set will not allow duplicate values but I don't understand why 1 and 2 is still duplicated.
This is because this is undefined behavior.
nums.erase(itr);
std::vector's erase() method invalidates all existing iterators "at or after the point of the erase". Since itr is the "point of the erase", itr is no longer a valid iterator when erase() returns. Subsequent attempt to increment it, in the for loop's iteration results in undefined behavior.
Your C++ textbook will have a more complete explanation of how to use the value that erase() returns, and what it means, in order to correctly avoid undefined behavior; but the capsule summary is:
itr=nums.erase(itr);
Note that now itr points to the value in the vector that's already after what was erase()d, which might be end(); whether it's end() or not you obviously don't want to increment it immediately. It should be obvious that you want to check if the immediately following value in the vector is another duplicate too, don't you agree?
So what you'll need to slightly rework your loop so that it:
Uses erase() correctly
Only increments the iterator if it does not erase() the duplicate value.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have n vectors and I need to iterate over all of them consistently.
I mean that first I need to iterate over all elements of first vector then to iterate over all elements of second vector and so on.
I have task to compare all elements consistently including the last element of k-1'th vector and first element of k'th vector.
I know the solution where I first concatanete all this vectors in one big final vector and then iterate over final vector.
But it seems to me that this solution wastes a lot of memory and time.
Please help me to find more optimized solution.
If it exists.
For example, with complexities: O(1) additional memory and O(n) time .
A simple approach would be to use two nested loops.
In C++11 and later, simply do
std::vector<std::vector<int> > vec;
// some code that sets up the vectors in vec
for (auto &v : vec) // iterate over the vectors in vec
{
for (auto &e : v) // iterate over the elements of v
{
// do whatever is needed to element e
}
}
If need be, v and e may be const qualified (to indicate not changing the vectors or their elements). The total number of iterations will be the number of elements of the contained vectors. The additional memory usage will be (at any point in time in the inner loop) two sets of references - one set for controlling the inner loop and one for the outer loop (i.e. no copies of the vectors or elements themselves).
Before C++11, the above loops can be rewritten less verbosely using for loops that work with iterators rather than ranges;
for (std::vector<std::vector<int> >::iterator v(vec.begin()), vend(vec.end());
v != vend; ++v)
{
for (std::vector<int>::iterator e(v->begin()), eend(v->end());
e != eend; ++e)
{
// do whatever is needed to element *e
}
}
Note the need to dereference iterators in this form.
If you only need something that can be iterated over, you probably want something like ranges::view::concat
Given N source ranges, produce a result range that is the concatenation of all of them.
This doesn't copy any values, so is O(1) storage and O(1) time.
If the thing you need is exactly std::vector<MyClass>, then you are out of luck, you will have to populate a vector with all the values.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a std::vector<string> called v. I'd like to read in a string from the user and remove it from v. Here's what I have so far:
string rnames;
cout << "Enter the string to remove " << endl;
cin >> rnames;
v.erase(rnames);
This produces an error.
Any ideas how we can make this to work? Do we first need to find the rnames and then erase it?
The std::vector's erase method takes in an iterator saying which entry in the vector you want to remove. It doesn't work like the map or set where you can call erase to remove a specified key.
To remove a single copy of an element from a std::vector, you can use std::find and the std::vector's erase member function like this:
auto itr = std::find(v.begin(), v.end(), rnames);
if (itr != v.end()) v.erase(itr);
The above code assumes you're using C++11, which all major modern compilers support. However, it seems like you're using an older compiler that doesn't support C++11, so you'd have to write something like this:
std::vector<string>::iterator itr = std::find(v.begin(), v.end(), rnames);
if (itr != v.end()) v.erase(itr);
To remove all copies of an element from a vector, you can use std::remove like this:
v.erase(std::remove(v.begin(), v.end(), rnames), v.end());
(This requires the <algorithm> header.) That being said, if you find that you are often removing elements from a std::vector and you have a large number of elements in the vector, you may want to consider changing data structures to something that more efficiently supports removals.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am creating function, which takes a vector of operators( different matrices). Operators can be provided in different ordering ( from the smallest to biggest or other way around).
I need to create for loop based on ordering
for(auto tr = operators.begin(); tr != operators.end() ; ++tr )
or
for(auto tr = operators.end(); tr != operators.begin() ; --tr )
content inside of loop stays same
is there any way how to do this automatically? maybe based on some help input parameter?
You can support this by having your function consume a pair of iterators (a "range") instead of a complete matrix or vector. For example:
template <typename Iterator>
void print(Iterator begin, Iterator end) {
for(auto tr = begin; tr != end; ++tr)
; // ...
}
This way, you can pass any sort of range in: forward, reverse, or others. This is how much of the STL is designed.
If you use a std::vector for example, you'd invoke the above like so:
std::vector<int> vec;
print(vec.begin(), vec.end()); // forward
print(vec.rbegin(), vec.rend()); // reverse
Although, technically, an end() iterator can often be decremented and dereferenced safely, you are relying on specific properties that not all iterators are guaranteed to have.
A number of standard containers [some introduced in C++11 do not] have both forward iterators (which iterate through elements in order) and reverse iterators (which iterate over elements in the opposite order). The counterparts of begin() and end() are rbegin() and rend() respectively.