Alternative to range-based for loops in c++ - c++

Is there any alternative to a range-based for loop when it comes to vector arrays? I've noticed that c++98 won't allow range-based for loops. Here is some sample code looping through a vector array using a range based for loop:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vecArray1 (3,20);
for (int v: vecArray1) {
cout << "ArrayValue:" << v << endl;
}
return 0;
}
Now here is an alternative I've tried that didn't work:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vecArray1 (3,20);
for (int i=0; i<sizeof(vecArray1); ++i) {
cout << "ArrayValue:" << vecArray1[i] << endl;
}
return 0;
}
It outputs 10 elements instead of 3 defined by the vector array above. Are there any alternatives to range-based for loops that work with c++98?

C++98 does not allow for range-based for-loops.
In C++98 you would need to do the following:
for(unsigned int i=0;i<vecArray.size();++i)
std::cout << "ArrayValue: " << vecArray[i] << std::endl;
or
for(std::vector<int>::iterator it=vecArray.begin();it!=vecArray.end();++it)
std::cout << "ArrayValue: " << *it << std::endl;
The operator
sizeof
does NOT give you the length of an array. Instead, it returns an unsigned integer representing the number of bytes of the type you give as the argument.
For example,
std::cout << sizeof(unsigned long long) << std::endl;
prints
8
on my machine, because the type unsigned long long consista of 64-bits, or 64/8 = 8 bytes.
In C++11 we now have range-based for-loops:
Examples:
for(int i : vecArray)
std::cout << "i = " << i << std::endl;
for(const int& i : vecArray)
std::cout << "i = " << i << std::endl;
In the first example the values are copied from vecArray into the variable i. In the second example you are instead working with const references to the values in vecArray (which could be useful for objects which are expensive to copy).
In fact, the range-based for loops in C++11 are available for all types on which you can call begin() and end() (i.e. those which you can iterate through).

sizeof(vecArray1) doesn't do what you think it does.
Either use:
for (int i=0; i<vecArray1.size(); ++i) {
cout << "ArrayValue:" << vecArray1[i] << endl;
}
or:
for (std::vector<int>::iterator it = vecArray1.begin(); it != vecArray1.end(); it++) {
cout << "ArrayValue: " << *it << endl;
}
The second one is more verbose, but works for other types of collections as well (like std::list) and is more similar to what the range-based for loop does.

Related

accessing elements of dynamic array of lists

So, I don't know how can I print elements of such a list.
list<int>* a;
a = new list<int>(4);
a[0].push_back(1);
a[0].push_back(3);
a[2].push_back(5);
a[2].push_back(7);
cout << a[0].front() << '\n';
cout << a[1].back() << '\n';
Firstly, I tried to print it via range-based for loop, but it didn't work either.
for(auto element: a[0]) cout << element << '\n'; // doesn't work
Are you trying to store a list of integer lists? Because this implementation will not work since you only have a list of integers and no push_back() operation is available for the elements.
Remove the index operator for all those push_back() operations and take out the index operator for the front() and back() as those are not available to the elements either.
I would use a std::vector instead of new (which should technically be new[] in this case anyway).
#include <iostream>
#include <list>
#include <vector>
int main() {
std::vector<std::list<int>> a(4);
a[0].push_back(1);
a[0].push_back(3);
a[2].push_back(5);
a[2].push_back(7);
for (std::list<int> const& l : a) {
for (int i : l) {
std::cout << i << ' ';
}
std::cout << '\n';
}
}
Output
1 3
5 7

What is the behaviour of vector<T>().swap(x)?

I'm currently trying to re-implement the vector container. I just read on this website that vector<T>().swap(x);, where x is a vector previously declared, could be used to clear and reallocate the x vector to 0.
I realized with this example that I'm not familiar with the use of a constructor (or what I think is a constructor).
#include <iostream>
#include <string>
#include <vector>
typedef std::string T;
void display(const std::vector<T>& input) {
std::cout << "------START------" << std::endl;
for (int i = 0; i < input.size(); i++)
std::cout << input[i] << std::endl;
std::cout << "------END-------" << std::endl;
std::cout << "input size: " << input.size() << std::endl;
std::cout << "input capacity: " <<input.capacity() << std::endl;
}
int main() {
std::vector<T> src(1, "Matthieu0");
std::vector<T> empty;
src.push_back("Guillaume1");
src.push_back("Paul2");
src.push_back("Julien3");
std::vector<T> tmp(src);
std::cout << "------swap1------" << std::endl;
display(empty);
empty.swap(tmp);
display(empty);
std::cout << "------swap2------" << std::endl;
display(src);
std::vector<T>().swap(src);
display(src);
return 0;
}
So, I have no problem understanding swap1 behavior, crystal clear. But I don't understand what is happening under the hood with swap2 and how I could implement it.
But I don't understand what is happening under the hood with swap2
When you wrote
//-vvvvvvvvvvvvvvvv------------->a temporary std::vector
std::vector<T>().swap(src); //this calls swap on the temporary(unnamed) std::vector
In the above statement you're calling std::vector::swap on the temporary(unnamed) std::vector created from the expression std::vector<T>().
This is similar to the swap1 that you did with the exception that in swap1 you were calling std::vector::swap on a named object empty but here you're calling it on the temporary object.
Many developers want to release memory occupied by a vector after std::vector::resize(0).
It can be done since C++11 by calling std::vector::shrink_to_fit(). There is no such method until C++11, in C++98, and developers use such a trick:
Create an empty vector.
Swap contents of vectors.
Destroy the vector created on the step 1.
For performing the step 3 as much earlier as possible, the limited scope block { ... } is used.
std::vector<int> v(10);
std::cout << v.size(); << std::end; // prints 10
{
std::vector<int> tmp;
std::cout << tmp.size(); << std::end; // prints 0
v.swap(tmp);
std::cout << tmp.size(); << std::end; // prints 10
}
std::cout << v.size(); << std::end; // prints 0
It can be shorter if an unnamed temporary vector generated by a compiler is used. The life time of an unnamed temporary variable is well known:
std::vector<int> v(10);
std::cout << v.size(); << std::end; // prints 10
v.swap(std::vector<int>());
std::cout << v.size(); << std::end; // prints 0
std::vector<int> v(10);
std::cout << v.size(); << std::end; // prints 10
std::vector<int>().swap(v);
std::cout << v.size(); << std::end; // prints 0
It can be still used since C++11 for making
v.resize(0);
v.shrink_to_fit();
shorter and to guarantee freeing memory:
v.swap({});

std::vector<int> allocated with (n,0) is not iterable

Consider the following code:
#include <vector>
#include <iostream>
void monitor_vector(std::vector<int> myV)
{
std::vector<int>::iterator it = myV.begin();
std::cout << "Vector size: " << myV.size() << std::endl;
while (*it)
{
std::cout << "Element " << it-myV.begin() << ": " << *it << std::endl;
it++;
}
}
int main()
{
std::vector<int> myVector(4,1);
monitor_vector(myVector);
return 0;
}
Basically, I create a std::vector<int> that has 4 elements, and assign each element 1. When I execute this code, all is well. The output shows each element.
However, when I execute it with this line
std::vector<int> myVector(4,1);
replaced by this line:
std::vector<int> myVector(4,0);
I can't see any output. The output is:
yilmazali#yilmazali:~/cpp_practice$ g++ -o la vector_practice.cpp
yilmazali#yilmazali:~/cpp_practice$ ./la
Vector size: 4
yilmazali#yilmazali:~/cpp_practice$
Why does it ignore the elements with default integer value? Still, they are there as the member of std::vector.
Thanks for your time,
Ali
You iterate while (*it).
If you fill your vector with zeros, *it == 0 and therefore if (*it) is like if (false): the loop body is never executed.
Instead, loop while it != myV.end()

Array of int or vector?

i'm trying to store some elements that is going to change every time, but i don't know which
way is better and why. I'm thinking about two ways, 1) declaring array of int and loop or
use vector's.
Which way is better and why?
Does declaring array of int have any future memore problems as leak?
the code down below show the two ways i'm talking about:
1)
#include <iostream>
#include <vector>
int main()
{
int x[5];
x[0] = 10;
x[1] = 20;
x[2] = 30;
x[3] = 40;
x[4] = 50;
for(unsigned int i = 0;i<=sizeof(x[5]); i++)
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
system("pause");
return 0;
}
2)
#include <iostream>
#include <vector>
int main()
{
std::vector<int> x;
x.push_back(10);
x.push_back(20);
x.push_back(30);
x.push_back(40);
x.push_back(50);
for(unsigned int i = 0;i<=x.size()-1; i++)
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
system("pause");
return 0;
}
If this is all you have to do, and your array will always have a size that is known at compile time, then you do not need std::vector.
On the other hand, in C++11 you could use std::array instead of a plain C array (std::array is a zero-overhead, safer and more functional wrapper over a C array):
#include <iostream>
#include <array>
int main()
{
std::array<int, 5> x = { 10, 20, 30, 40, 50 };
for (unsigned int i = 0; i < x.size(); i++)
// ^^^^^^^^
{
std:: cout << "x[" << i << "] = "<< x[i] << std::endl;
}
}
Here is a live example. Notice, that std::array offers a size() member function which you may want to use instead of the sizeof operator.
Moreover, since std::array is a standard sequence container, you could iterate through its element this way:
std::size_t i = 0;
for (auto e : x)
{
std:: cout << "x[" << i++ << "] = "<< e << std::endl;
}
Here is a live example.
If the size is known at compile time, use std::array. If not, use std::vector. In either case, use iterators to look at the elements:
typedef std::array<int> my_container_type;
typedef my_container::iterator iterator;
my_container_type my_container = { whatever };
for (iterator it = my_container.begin(); it != my_container.end(); ++it)
std::cout << "x[" << (it - my_container.begin()) << "] = " << *it << '\n';
By using iterators you greatly reduce the risk of accidentally using a loop limit like sizeof(x[5]), which is nonsense.
Neither is "better". They both address entirely different use cases.
If you know the array size at compile time and are 100% sure it will never change, sure, use a plain old array. It has less overhead, and the compiler can even aid you with static analysis by spotting any attempts to read outside the boundaries.
On the other hand, if you are unsure of the array's side (i.e. you will be reading input from a file or the user), then use the std::vector. It can grow to any size to meet your needs.

C++ iterator behaviour in for vs while loops

I do not understand why iterating through a container with a for loop produces different results than iterating through it with a while loop. The following MWE illustrates this with a vector and a set of 5 integers.
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int main()
{
vector<int> v;
set<int> s;
// add integers 0..5 to vector v and set s
for (int i = 0; i < 5; i++) {
v.push_back(i);
s.insert(i);
}
cout << "Iterating through vector with for loop.\n";
vector<int>::const_iterator itv;
for (itv = v.begin(); itv != v.end(); itv++) cout << *itv << ' ';
cout << '\n';
cout << "Iterating through set with for loop.\n";
set<int>::const_iterator its;
for (its = s.begin(); its != s.end(); its++) cout << *its << ' ';
cout << '\n';
cout << "Iterating through vector with while loop.\n";
itv = v.begin();
while (itv++ != v.end()) cout << *itv << ' ';
cout << '\n';
cout << "Iterating through set with while loop.\n";
its = s.begin();
while (its++ != s.end()) cout << *its << ' ';
cout << '\n';
}
The above produces:
Iterating through vector with for loop.
0 1 2 3 4
Iterating through set with for loop.
0 1 2 3 4
Iterating through vector with while loop.
1 2 3 4 0
Iterating through set with while loop.
1 2 3 4 5
The for loops work as expected but not the while loops. Since I'm using ++ as a postfix, I don't understand why the while loops behave as they do. Another mystery is why the while loop prints a 5 for set s, since this number was not inserted in s.
Your while loop is not equivalent to the for loop.
The for loop is equivalent to
itv = v.begin();
while(itv != v.end()) {
cout << *itv << ' ';
itv++;
}
Note that the increment happens after the cout. In your while loops, you do the increment in the test, before cout. Even though you use postincrement, the increment takes effect before your loop body is executed.
Write your while loops like I did there and the discrepancy should disappear.
When you iterate using the for loop you increment the iterator only after the body is evaluated. When you iterate using the while loop you increment the iterator after the check but before the body of the loop. Dereferencing the iterator in the last iteration of your while loops causes undefined behavior.
It could be because the compiler evaluates the its++ in the while expression first before evaluating the rest of the expression.
Since I'm using ++ as a postfix, I don't understand why the while loops behave as they do.
That's because first the while predicate is evaluated, and then (if the predicate was true) the body of the while loop. By the time you try to access the value in the body, the iterator was already incremented.
Just a few 'random' style hints, mainly showing algorithm use and modern C++11 features.
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <iterator>
int main()
{
const std::vector<int> v { 0,1,2,3,4 };
const std::set<int> s { 0,1,2,3,4 };
for (auto element : v)
std::cout << element << ' ';
std::cout << '\n';
for (auto element : s)
std::cout << element << ' ';
std::cout << '\n';
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
std::copy(s.begin(), s.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
}