Loop prints only the first vector element

I'm generating random numbers and adding them into a vector then printing the numbers in the vector but it shows me only the first number.
When I put a breakpoint and go through, then it works fine, it shows me all the random generated numbers in the vec.

Output is: "16 16 16 16 16" (random number)
What seems to be the problem?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <time.h>
#include <vector>


int main() {

    std::vector<int> vec{};

    for (int i{}; i < 5; i++) {
        std::srand(static_cast<unsigned int>(std::time(nullptr)));
        int x = rand() % 100 + 1;
        vec.emplace_back(x);
    }

    for (const auto i : vec) {
        std::cout << i << " ";
    }
    
    return 0;  
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <ctime>
#include <vector>


int main() {

    std::vector<int> vec{};

    std::srand(static_cast<unsigned int>(std::time(nullptr)));
    
    for (int i{}; i < 5; i++) {
        
        int x = rand() % 100 + 1;
        vec.emplace_back(x);
    }

    for (const auto i : vec) {
        std::cout << i << " ";
    }
    
    return 0;  
}


85 5 17 85 84
Oh the srand needs to be out.
Thank you!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <random>  // http://www.cplusplus.com/reference/random/
#include <vector>

int main()
{
   // set the size of the vec, no 'magic numbers'
   const size_t size { 5 };

   // create a C++ random engine (one of several available)
   // seeding it with the non-deterministic random engine
   std::default_random_engine prng(std::random_device{}());

   // create a distribution 1 - 100 inclusive
   std::uniform_int_distribution<int> dist(1, 100);

   // create a vector of known size (no need for push_back)
   std::vector<int> vec(size);

   for (size_t i { }; i < size; ++i)
   {
      // create a random number, assign to an element
      vec[i] = dist(prng);
   }

   // use a reference to access the vector itself instead of a copy
   for (const auto& itr : vec)
   {
      std::cout << itr << ' ';
   }
   std::cout << '\n';
}
95 20 56 78 96
Thanks George, I didn't know about the <random> header, I'm still learning c++.
First, the srand() and rand() are functions from C Standard Library. They have known issues. C++ Standard Library has much better tools for "random". George P shows how to use them. Learn the C++ tools.


The rand() has a known serie of values. Each call of rand() returns the next value from that serie.
The srand() resets rand() to specific point in the serie, sets where to read the next value from.

In a quick loop the time does not change between calls of srand(). Therefore, every call of rand() reads the same value from the serie.
When you debug the program, which can slow down execution, the time can advance between calls to srand() and therefore each rand() will return a value from different part of the serie. Different value.


You essentially had:
1
2
3
4
5
6
7
8
std::vector<int> vec{};
for ( int i{}; i < 5; i++) {
  vec.emplace_back( 16 );
}

for ( const auto i : vec ) {
  std::cout << i << " ";
}

And assumed due to output that the loop did same as:
1
2
3
for ( const auto i : vec ) {
  std::cout << vec[0] << " ";
}


Lets suppose that you had generated random numbers, but that serie would have been:
2032415, 15, 715, 672315, 3415
These too would have produced the 16, 16, 16, 16, 16.
(It is quite unlikely that anywhere in the rand() serie are five consecutive *15, but not impossible.)
https://www.learncpp.com/cpp-tutorial/random-number-generation/

The C random generator should be avoided when writing C++ code, it is notoriously bad at generating evenly distributed numbers.

https://web.archive.org/web/20180123103235/http://cpp.indi.frih.net/blog/2014/12/the-bell-has-tolled-for-rand/

http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3551.pdf

Do you understand why you should use a reference in a range-based for loop? Your for loop worked on a copy of the vector, so no need for const. Even if you altered the elements in your loop the vector's contents wouldn't have been changed.

Range-based for loops are AKA for-each loops.

https://www.learncpp.com/cpp-tutorial/for-each-loops/
Oh, something else.....repeatedly inserting new elements into a vector can be a performance killer, the vector may more than once allocate new memory as the vector grows in size. Glomming onto new chunks of memory takes time.

If you know the number of elements your vector will likely hold instantiate it with that number of elements from the beginning.

Something similar happens when repeatedly deleting elements from the vector, "DIE Performance!"
Last edited on
That's right keskiverto, I thought the loop did vec[0].
The thing is I can't distinguish C from C++. I watch all sort of tutorials and they don't say if that is C or C++.

@George
I knew about the reference in the for loop, I just forgot to add it.
But what if you don't know the size of the vector, what do you use then for performance?
If you don't know the eventual size of the vector then adding elements is the only viable choice.

You could specify what you THINK might be the eventual size (plus a bit more) from the start, std::vector<int> vec(100); so you don't have the potential constant allocation issues.

Similar to how C programmers would over-size a C string larger than what they would expect.

You want to learn more of C++, then wander over to Learn C++: https://www.learncpp.com/

One of the best free online tutorials for C++. While it doesn't delve into ALL of what C++ has to offer, it does cover much of what is available.

There is considerable overlap between C and C++. The core languages are red-headed step-children of each other.

Take ISO standard C code and for the most part a C++ compiler will not choke on the code.

Though more and more C++ has C++ ways to do what C does. Displaying formatted data with printf, for example. C++20 now has std::format in the <format> formatting library.

https://en.cppreference.com/w/cpp/utility/format

mikef wrote:
I knew about the reference in the for loop, I just forgot to add it.

Heh, I know, I forget exact coding procedures all the time. I forget/change something and wonder why I get crap results. Then I look at what I actually coded instead of what I THOUGHT, and *BINGO!*
You could specify what you THINK might be the eventual size (plus a bit more) from the start, std::vector<int> vec(100); so you don't have the potential constant allocation issues.

That creates a vector that has 100 elements.
Calling vec.emplace_back(16); will add, so the vector has then 101 elements.
(Besides, what do we know about the values in the first 100 elements?)

1
2
3
std::vector<int> vec; // empty vector
vec.reserve(100); // still empty vector, but with some preallocated memory
vec.emplace_back(16); // vec has one element and room for 99 more before it has to reallocate 


On the reference:
1
2
3
4
std::vector<int> vec{};
for ( const auto i : vec ) {
  std::cout << i << " ";
}

In this case the i is an int. Do you think it to be significantly more efficient to use reference to int, rather than make a copy of the value?
I was going to add an additional comment that mentioned using reserve after the bit you quoted, but a rather nasty bout of RL intervened. I was going to come back after the recovery, but you had already done it for me.
Topic archived. No new replies allowed.