-1

Why there is an atomic variable in the code below? - because it is part of a larger code base where the m_subscriptions array is being updated from multiple threads. Please bear with me on that one ..

Here is my question:

#include <iostream>
#include <atomic>
#include <algorithm>
#include <iterator>


#define MAX_SUBSCRIPTIONS 45

static std::atomic<int> numberOfSubscriptions;

int main ()
{
    int m_subscriptions[MAX_SUBSCRIPTIONS] = {};
    numberOfSubscriptions.fetch_add(0, std::memory_order_relaxed);

    m_subscriptions[numberOfSubscriptions] = 12;
    numberOfSubscriptions.fetch_add(1);
    m_subscriptions[numberOfSubscriptions] = 13;
    numberOfSubscriptions.fetch_add(1);
    m_subscriptions[numberOfSubscriptions] = 14;
    numberOfSubscriptions.fetch_add(1);
    m_subscriptions[numberOfSubscriptions] = 15;
    numberOfSubscriptions.fetch_add(1);
    m_subscriptions[numberOfSubscriptions] = 16;
    numberOfSubscriptions.fetch_add(1);

    for ( int i = 0; i < numberOfSubscriptions; i++ )
        std::cout << m_subscriptions[ i ] << "\t "; 

    std::cout << std::endl;

    auto result = std::find(m_subscriptions, m_subscriptions + numberOfSubscriptions, 44);

    if ( result == std::end(m_subscriptions) )
        std::cout << "Not Found" << std::endl;
    else 
        std::cout << *result << std::endl;
}

does not print "Not Found" when I pass something that is not present in the array.

If I replace if ( result == std::end(m_subscriptions) ) with

if ( result == (m_subscriptions + numberOfSubscriptions) ) it works !

HOW ??

How does std::find come to know how many values in m_subscriptions have been initialized ? Should it not go on till the end i.e. m_subscriptions[MAX_SUBSCRIPTIONS] like one would expect a dumb computer to ?

In other words, why does std::find stop searching for 44 at m_subscriptions + numberOfSubscriptions? Why does it not go on till m_subscriptions[MAX_SUBSCRIPTIONS] ?

Chani
  • 5,055
  • 15
  • 57
  • 92

2 Answers2

5

std::find has no knowledge of the array or the elements that are initialised within it. You told it where to stop with the second argument:

std::find(m_subscriptions, // Start here
          m_subscriptions + numberOfSubscriptions, // Stop here
          44); // Try to find this

If it doesn't find what you're looking for, it just returns that second argument back, which is the end of the range that you gave it.

If you had passed std::end(m_subscriptions) as the second argument, it would have iterated over all the elements that you haven't assigned to. However, it's wroth noting that these aren't uninitialised, they have been value initialised. When you do aggregate initialisation with {}, any members of the aggregate that you haven't specified are value initialised. Regardless, even if they were uninitialised, there's no way to tell whether something has been initialised or not.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
2

std::find needs the end iterator, and points to it where element not found

m_subscriptions + numberOfSubscriptions points to last element added

whereas std::end(m_subscriptions) points to pass the total capacity (45)

Try printing these :

std::cout  << result - m_subscriptions ; // 5 with search element not in list
std::cout <<  std::end(m_subscriptions)  - m_subscriptions ; //45
P0W
  • 46,614
  • 9
  • 72
  • 119