Is this legal use of a for loop? - c++

For instance:
vector<int> something;
//imagine i add some elements to the vector here
int* pointy;
for (int i = 0; i < something.size(); pointy = &something[i++]) {
//do some work with pointy
}
it seems to work and saves me a line but is there any danger of weird bugs popping up down the line because of this?

This may not be legal, because pointy is unassigned on the first iteration. If the loop does not dereference pointy during the initial iteration, it may be OK, but it is not possible to tell without seeing the body of the loop.
Since you are using std::vector, using iterators would save you another line, because you wouldn't need to declare pointy. You would be able to determine the offset without i by subtracting something.begin() from the current iterator:
for (vector<int>::iterator iter = something.begin() ; iter != something.end() ; ++iter) {
cout << "Item at index " << (iter - something.begin()) << " is " << *iter << endl;
}

Yes, that is dangerous, as dasblinkenlight pointed out. But there's a simpler way to eliminate this kind of problems.
Write your code for simplicity and readability first. Compressing your loop into the smallest possible number of lines won't add anything in terms of performance, and even if it did, you shouldn't care as long as your profiler doesn't tell you that your loop is a bottleneck.
On the other hand, it will make your code harder to read and, possibly, more prone to bugs (as you've probably noticed).
In C++11, consider using a range-based for loop:
for (int& p : something)
{
// ...
}
In C++03, consider using std::for_each(), or a classical loop based on iterators:
for (std::vector<int>::iterator i = something.begin(); i != something.end(); ++i)
{
// use *i to refer to the current pointy
// use (i - something.begin()) to get its index
// ...
}

It is very dangerous, because i is not unsigned. It can blow up in some rare cases. :)

Is this safe really depends on what you are after.
pointy is going to be a pointer to an element in the vector.
This means that if you change the value of pointy, or what it points to be more specific, you are actually changing the content of the vector for that specific element.

As for me, I like to handle std::vector like this for larger Objects:
std::vector<int*> mynumbers;
//add elements here like this:
int somenumber = 5;
mynumbers.push_back(&somenumber);
for(int i=0;i<elemnts.size();i++)
{
cout << "Element Nr. " << i << ": " << *elements.at(i) << endl;
//modify like this:
*elements.at(i) = 0;
}
The pointer instead of the variable itself is because std::vector handles pointers faster than large objects itself, but for int, this doesn't really make much difference so you can also do it like this:
std::vector<int> mynumbers;
mynumbers.push_back(5);
int* pointy
for(int i=0;i<elemnts.size();i++)
{
pointy = &elements.at(i);
}
Works great for me!

Related

How come my vector array won't output anything after I erase an element?

Recently I've started learning C++, and everyday I do a C++ practice exercise to understand the language more. Today I was learning Vector Arrays and I hit a roadblock.
I'm trying to make a simple program that takes an array, puts it into a vector, then removes all the odd numbers. But for some reason when I erase an element from the vector, and output the modified vector, it doesn't output anything.
If somebody could guide me to the right direction on what I'm doing wrong, that would be great!
remove.cpp
#include <iostream>
#include <vector>
using namespace std;
class removeOddIntegers {
public:
void removeOdd(int numbs[]) {
vector<int> removedOdds;
for(int i = 0; i < 10; ++i) {
removedOdds.push_back(numbs[i]);
}
for(auto i = removedOdds.begin(); i != removedOdds.end(); ++i) {
if(*i % 2 == 1) {
removedOdds.erase(removedOdds.begin() + *i);
std::cout << "Removed: " << *i << endl;
}
}
for(auto i = removedOdds.begin(); i != removedOdds.end(); ++i) {
std::cout << *i << endl; //doesn't output anything.
}
}
};
main.cpp
#include <iostream>
#include "remove.cpp"
using namespace std;
int main() {
removeOddIntegers r;
int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
r.removeOdd(numbers);
return 0;
}
Now, I understand that I could just filter through the array, and only push_back the even numbers to the vector, and quite frankly, that works like a charm. But I want to understand why my method doesn't work. How come when I remove an element from the vector, it just fails to output anything?
Thanks in advance!
There's a few things wrong, but they mostly boil down to the same fundamental issue. You are violating iterator guarantees of std::vector::erase:
Invalidates iterators and references at or after the point of the erase, including the end() iterator.
You do this both when dereferencing the deleted iterator to display your "removed" message, and also when calling ++i for the loop.
In addition, your call removedOdds.erase(removedOdds.begin() + *i); is wrong, because it's using the actual value in the vector as an offset from the beginning. That assumption is completely wrong.
The proper way to erase an element at an iterator and retain a valid iterator is:
i = removedOdds.erase(i);
Here is your loop with minimum changes required to fix it:
for (auto i = removedOdds.begin(); i != removedOdds.end(); ) {
if (*i % 2 == 1) {
std::cout << "Removed: " << *i << endl;
i = removedOdds.erase(i);
} else {
++i;
}
}
Notice how the iterator is advanced in the body of the loop now. You can do a thought experiment to think about why. Or you can try doing it the wrong way and use an input like { 1, 3, 5, 7, 9 } to demonstrate the problem.
This is still not the idiomatic way to remove elements from a vector. As you alluded to, elements should be swapped to the end of the vector. The reason for this is that std::vector::erase is a linear operation that must shuffle the entire remainder of the vector. If you do this multiple times, you essentially have O(N^2) time complexity.
The recommended approach is to use std::remove_if:
removedOdds.erase(removedOdds.begin(),
std::remove_if(removeOdds.begin(), removeOdds.end(),
[](int n) { return n % 2 == 1; }));
The flaw in the shown algorithm is more easily observed with a much simpler example:
for(int i = 0; i < 2; ++i) {
removedOdds.push_back(numbs[i]);
}
This initializes the vector with just two values: 0 and 1. This is small enough to be able to follow along in your head, as you mentally execute the shown code:
for(auto i = removedOdds.begin(); i != removedOdds.end(); ++i) {
Nothing interesting will happen with the first value, 0, that gets iterated here. ++i increments the iterator to point to the value 1, then:
if(*i % 2 == 1) {
removedOdds.erase(removedOdds.begin() + *i);
std::cout << "Removed: " << *i << endl;
}
This time erase() removes 1 from the vector. But that's what i is also pointing to, of course. Then, if you look in your C++ reference, you will discover that std::vector::erase:
invalidates iterators and references at or after the point of the erase,
including the end() iterator.
i is now "at the point of the erase", therefore, i is no longer a valid iterator, any more. Any subsequent use of i becomes undefined behavior.
And, i immediately gets used, namely incremented in the for loop iteration expression. That's your undefined behavior.
With the original vector containing values 0 through 9: if you use your debugger it will show all sorts of interesting kinds of undefined behavior. You can use your debugger to see if the shown code ever manages to survive when it encounters a higher odd value, like 7 or 9. If it does, at that point this vector will obviously be much, much smaller, but removedOdds.erase(removedOdds.begin() + *i); will now attempt to remove the 7th or the 9th value in a vector that's about half its size now, a completely non-existent value in the vector, with much hilarity ensuing.
To summarize: your "method doesn't work" because the algorithm is fundamentally flawed in multiple ways, and the reason you get "no output" is because the program crashes.

Cout a whole array in c++

I am fairly new to c++, is there a way in c++ through which we can cout a whole static array apart from iterating via a for loop?
int arra[10] = {1,2,3,4};
std::cout << arra << std::endl;
I tried this but, this is printing address of the first element in the array.
Following doesn't use (explicitly) loop:
std::copy(std::begin(arra),
std::end(arra),
std::ostream_iterator<int>(std::cout, "\n"));
but loop seems simpler to read/write/understand:
for (const auto& e : arra) {
std::cout << e << std::endl;
}
#include<iostream>
using namespace std;
int main(){
int i;
int myarr[5]={9,84,7,55,6};
for(i=0;i<5;i++){
cout<<myarr[i]<<endl;
}
}
Some how you are going to have to visit each element of the array to display the contents. This can be done long form or use a loop. Fortunately we can use std::copy to fide the loop and display the array.
int arr[] = {1,2,3,4,5};
std::copy(std::begin(arr), std::end(arr), std::ostream_iterator<int>(std::cout, " "));
Live Example
You need to either loop over the array
int arra[10] = {1,2,3,4};
for (int i = 0; i<sizeof(arra)/sizeof(arra[0]); ++i)
{
std::cout << arra[i] << std::endl;
}
or use
std::copy(std::begin(arra), std::end(arra), std::ostream_iterator<int>(std::cout,"\n"));
As you asked to do this without an Array, you could easily do this:
std::copy(arra, arra + 10,
std::ostream_iterator<int>(cout, "\n"));
If you want to write good code, you could use std::array and then simply write arra.begin() and arra.end().
There are basically two ways. First one is a loop somewhere . The loop can be explicit - in your code - or it can be implicit through library. Example of library loop:
std::for_each(cbegin(arra), cend(arra), [](int i) {std::cout << "i ";});
The second way of printing the array is with the use of recursion. Here is example of the code:
void print_element(const int* head, const int* tail) {
if (head == tail)
return;
std::cout << *head << " ";
print_element(head + 1, tail);
}
....
print_element(arr, arr + sizeof(arr) / sizeof(*arr));
Couple of words about recursion solution. Depending on your optimization, it can produce different results. Performance of the recursion will be roughly equivalent to the performance of the loop on any optimization level with AMD64 ABI. The reason for that is that arguments to functions are passed through registers (not pushed into stack), and the frame pointers are not used with any optimization. With this in mind, the only CALL/RET (which push/pop RIP) will slow down execution compared the loop, but this degradation is not measurable. The real issue, however, is that there is limited number of recursed calls which can be made on a given system (usually around single thousands), so printing an array of 1000000 elements is guaranteed to crash the application.
With higher levels of optimization which involve tail-call optimization, the recursion calls will be translated into plain jmps and the performance will be exactly the same as one with the loop. It will also eliminate the problem of maximum recursion level - so that arrays of any sizes can be printed.
It is printing address because you are pointing to an array, not its elements.
try this-
void printArray(int arr[], int n)
/* n is size here*/
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
}

which is faster method to traverse an array

Compare following two codes:
for (int i = 0; i<array_size; i++)
cout << array[i] << endl;
OR
int* p_end = array+array_size;
for (int* p_array = array; p_array != p_end; p_array++)
cout << *p_array << endl;
Which one is faster?
Another question is if we just want to traverse then which is faster: link list or array? Thankyou!
array[i] is potentially faster because the compiler knows you're not aliasing your pointer to someplace you really shouldn't.
Lists are much slower to traverse because of indirection imposed inbetween every node - this will ruin your caches and cause many a cache miss, which is probably the worst thing that can happen to a modern processor.
The first one is likely to be faster on an array.
The second one terminates on finding a zero entry in the structure. It really isn't the same thing. But suppose you changed your code to read:
p_array = array;
for (int i = 0; i < array_size; ++i, ++p_array)
cout << *p_array << endl;
That loop would probably take the same amount of time as the first one with any modern compiler. (In all actuality, the cost of cout would swamp everything anyway.)
The best approach for iterating through a container is really dictated by the container. vector<T> allows O(1) random access via operator[]. Also, its iterators offer O(1) operator++. In contrast, a container like list<T> only lets you use operator++, and it's O(1).
And final thought: You likely want to stick to pre-increment instead of post-increment in C++ when you can.
Note the following:
for (int i = 0; i<array_size; i++)
cout << array[i] << endl;
Each loop you must - compare i to array size, increment i, add i to array
int* p_end = array+array_size;
for (int* p_array = array; p_array != p_end; p_array++)
cout << *p_array << endl;
Each loop you must - compare p_array to p_end, increment p_array (there is no add here)
So it would seem that the second loop - becuase it does not have to do an add should be faster
However - optimizers can do quite a lot so I would recommend compiling both and then comparing the asm for each loop
Also for your second question - Arrays are faster than linked lists to traverse because of the load time for each node and because they take more memory so fewer nodes can be cached

accessing a specific point of a vector with an iterator

I am trying to figure out the best way of accessing a position in a vector using an iterator. I'm aware iterators behave like pointers, so this is the only method I came up with. I would like to know if there's a better or just a different way. Here's the code:
//This is a pointer to a vector of the class Particle BTW. vector < Particle > *particleList;
vector<Particle>::iterator it = particleList->begin();
// I assign a specific position outside the loop to a new iterator that won't be affected
vector<Particle>::iterator it2 = particleList->begin() + 3;
for( it; it != particleList->end(); it++){
it->draw();
//I'm interested in the velocity of this element in particular
cout << it2->vel << endl;
}
Thanks,
M
Try the following
for (auto i = particleList->begin(); i < particleList->begin(); ++i) {
i->draw();
std::cout << (i+3)->vel << "\n";
}
Note, there is no reason to use std::endl, std::endl has an implicit flush which lowers performance when outputting to say a log file, and when outputting to console it is already line buffered meaning that a line ending will already flush.
Note 2, you can only use + with i since i is a random access iterator because particleList is a std::vector, if you change say particleList to a std::list then the iterator will be a bidirectional iterator instead of a random access iterator and you will not be able to use + in that case you would need to use std::advance like WhozCraig mentioned, but do so on a copy like so:
for (auto i = particleList->begin(); i < particleList->begin(); ++i) {
i->draw();
auto i2 = i;
std::advance(i2, 3)
std::cout << i2->vel << "\n";
}
Though personally, in this case I would just iterate with two iterators instead of std::advance since std::advance is linear in time. Do something like:
auto i = particleList->begin();
auto i2 = particleList->begin();
std::advance(i2, 3);
for (; i < particleList->end(); ++i, ++i2) {
i->draw();
std::cout << i2->vel << "\n";
}
Note 3: (i+3) and i2 will run off the end of your list (vector), so do something smart there.

Printing out a list of pointers

I currently have created a List of pointers that point to every 5th element of another List of ints. I am trying to print out this list of pointer to ensure that it is pointing to the right elements of the other list.
I've tried various ways to do this but none of them seem to work.
for (int* t = pointersList.begin(); t != pointersList.end(); ++t)
{
cout << *t << endl;
}
or
for (int i = 0; i < pointersList.size(); ++i)
{
int* itr;
itr = pointersList.begin()+i;
cout << *itr;
}
I also tried accesssing it like a vector (cout << pointersList[i];) but none of these seem to work.
I understand that a pointer points to the memory location of an element (and that's where I use the *) but I never know when I am suppose to use a & or even &*.
Assuming that you're using a standard library container or one with a similar interface, then begin() and end() return iterators, not int*. In most cases, the code as is shouldn't compile.
Do the Following. This should work. This will get it to print your values of your pointers. Hope this is what you were looking for.
for(int a = 0; a < pointersList.size(); a ++)
{
std::list<int*>::iterator i = pointersList.begin();
advance(i, a);
int* totry = *i;
cout << *totry;
cout << ",";
}
You are having a serious problem in here. I just give you some hint hoping you find the answer in 10 minutes yourself.
In the first for loop you are increasing the pointer itself instead of the list.