1

I came across a piece of C++ code in one of my projects that initializes a vector with two inputs.

One of the inputs is an existing array, and the other is the same array plus the array length.

I found a similar piece of code on another site:

// Create an array of string objects
std::string arr[] = {"first", "sec", "third", "fourth"};

// Initialize vector with a string array
std::vector<std::string> vecOfStr(arr, arr + sizeof(arr)/sizeof(std::string));

for(std::string str : vecOfStr)
    std::cout << str << std::endl;

Can someone explain what arr + sizeof(arr)/sizeof(std::string) is?

The website that this code was referenced in said that this was the corresponding constructor used:

vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Khalid Akash
  • 197
  • 1
  • 9
  • *I found a similar piece of code on another site:* -- And when you're done with that code, change that line to `std::array arr = {"first", "sec", "third", "fourth"};` so that the number of elements is simply `arr.size()`, and not the often misused "sizeof" trick (that doesn't work if `arr` is passed to a function as a pointer). – PaulMcKenzie Jun 21 '18 at 02:58

2 Answers2

3

arr itself is of type std::string[4]. When passed to a function, it is decayed to pointer to the first element. In the expression arr + sizeof(arr)/sizeof(std::string), the first occurrence of arr is again decayed. The second is not. sizeof(arr)/sizeof(std::string) therefore evaluates to 4 which is the array extent. The whole expression arr + sizeof(arr)/sizeof(std::string) then evaluates to a pointer to the position past the final element in arr. This is usually called the off-the-end iterator. This effectively invokes the constructor vector(InputIterator first, InputIterator last, ...) where InputIterator is instantiated with std::string*.

Lingxi
  • 14,579
  • 2
  • 37
  • 93
0

Probably the most important thing here you need to understand what's happening is that std::string[] can be implicitly converted to std::string* (a pointer to the first element in the array).

So arr + sizeof(arr)/sizeof(std::string) in your example is a pointer to one past the end of the array (sizeof(arr)/sizeof(std::string) gives the number of elements in the array).

So the two elements being passed to vector's constructor are pointers, which can act as iterators, and initialise the vector with the four elements from arr.

John Ilacqua
  • 906
  • 5
  • 19