2

In the code below, what's the meaning of

vector<int> avector (arr, arr + sizeof(arr) / sizeof(arr[0]) );

in main()?

vector<int> bubbleSort(vector<int> avector) { //the vector for bubble sort
  for (int passnum = avector.size()-1; passnum > 0; passnum -= 1) {
      for (int i = 0; i < passnum; i++) {
          if (avector[i] > avector[i+1]) {
              int temp = avector[i];
              avector[i] = avector[i+1];
              avector[i+1] = temp;
          }
      }
  }
  return avector;
}

int main() {
    // Vector initialized using a static array
    static const int arr[] = {54,26,93,17,77,31,44,55,20};
    vector<int> avector (arr, arr + sizeof(arr) / sizeof(arr[0]) );

    vector<int> bvector = bubbleSort(avector);
    for (unsigned int i = 0; i < bvector.size(); i++) {
        cout<<bvector[i]<< " ";
    }
    return 0;
}

Thank you!

Jeff

JFMR
  • 23,265
  • 4
  • 52
  • 76
JeffZheng
  • 1,277
  • 1
  • 10
  • 13
  • maybe related https://stackoverflow.com/questions/33523585/how-do-sizeofarr-sizeofarr0-work – sp2danny Aug 13 '19 at 07:45
  • If `arr` is an array (not a pointer), as it is in your code, then `sizeof(arr)` is the size in memory of the entire array, `sizeof(arr[0])` is the size of an element of the array, so `sizeof(array)/sizeof(array[0])` is the number of elements in the array. In the definition of `avector`, `arr` is converted to a pointer (equal to `&arr[0]`) and `arr + sizeof(arr)/sizeof(arr[0])` is the address of one-past-the-end of `arr`. So the code is creating a vector that contains all the elements of `arr`. The technique does not work unless the compiler has visibility that `arr` is an array. – Peter Aug 13 '19 at 07:47
  • `sizeof(arr)/sizeof(arr[0])` is a C hack for getting the size of an array. In C++ the initialization should be written `vector avector(std::begin(arr), std::end(arr));`. – Pete Becker Aug 13 '19 at 13:22

3 Answers3

6
vector<int> avector (arr, arr + sizeof(arr) / sizeof(arr[0]) );

initializes an std::vector, avector, from the arr C-style array.

The arguments are iterators. These iterators define a range of elements:

  • arr: iterator to the first element of the range to be copied.
  • arr + sizeof(arr) / sizeof(arr[0]): iterator pointing the past-the-end element of the range to be copied.

The C++11 way would be to use the function templates std::cbegin() and std::cend() for C-style arrays:

vector<int> avector(std::cbegin(arr), std::cend(arr));

This approach takes advantage of template argument deduction for inferring the size of the C-style array. This way is less error-prone since it requires less typing.

JFMR
  • 23,265
  • 4
  • 52
  • 76
  • Thank you all for the detailed explanation! I started to learn C++ from the so-called modern C++ 14, so I had little idea of this old style. It's fun and interesting to learn. Thanks again! – JeffZheng Aug 13 '19 at 18:02
5

n = sizeof(arr) / sizeof(arr[0]) is the number of elements stored by the array.

avector(arr, arr + sizeof(arr) / sizeof(arr[0]) means copy the elements of the array arr to the vector avector from index 0 to n-1 (inclusive)

Ankit Kumar
  • 1,145
  • 9
  • 30
  • 3
    Possibly better to say "`0` to `n-1` (inclusive)" Saying "`0` to `n` (exclusive)" can be misinterpreted, particularly by non-native speakers (e.g. does it apply to both the `0` and the `n`, or [as you intend] to the `n`?) – Peter Aug 13 '19 at 07:51
2

avector is constructed via copying all elements of arr.

it uses the following constructor of the vector:

template< class InputIt >
vector( InputIt first, InputIt last, 
        const Allocator& alloc = Allocator() );
Oblivion
  • 7,176
  • 2
  • 14
  • 33