I am creating my own version of the vector container (patterned after the STL vector container) and have come across an interesting issue. I want to be able to assign values to my vector using the .at() function like:
vector<int> myVec1 = {1, 1, 3, 4};
myVec1.at(1) = 2; //assigning a value using .at()
So I did some experimenting, and I found that if I make my .at() function like this:
template <typename Type>
Type& My_vector<Type>::at(int const index) { //notice the ampersand(&)
return *(array + index);
}
then I am able to assign values just like in the STL vector class! I put the exclamation mark because to me, this is a surprise. My thoughts were that this use of the & operator would return the address of the value at the given index, and that doing something like:
My_vector<int> myVec1 = {1, 1, 3, 4};
myVec1.at(1) = 2;
would set the address of the second element of myVec1 to 2. This is not the case however, instead it changes the value there. This is good for me because my goal is to be able to assign a value using .at(), but my question is, what is the flaw in my thinking when I say that this function should return an address of the value at this point? How is the ampersand operator in my function definition actually working here? Can I say "it is returning a reference to the value of the array at the given index?" This seems to be what is happening, but wow, I thought I had a good grasp of how the & and * operators worked in most situations. Here is a fully functional example:
My_vector.h
#ifndef My_vector_h
#define My_vector_h
#include <cstring>
#include <type_traits>
#include <initializer_list>
template <typename Type>
class My_vector {
private:
Type* array;
int vector_size;
public:
//Copy Constructor
My_vector(std::initializer_list<Type> list) {
array = new Type[list.size() + 10];
vector_size = list.size();
memcpy(array, list.begin(), sizeof(Type) * list.size());
}
//Destructor
~My_vector() {delete [] array; array = nullptr;}
//Accessor .at()
int size() {return vector_size;}
Type& at(int const);
};
template <typename Type>
Type& My_vector<Type>::at(int const index) {
return *(array + index);
}
#endif /* My_vector_h */
main.cpp
#include <iostream>
#include "My_vector.h"
int main() {
My_vector<int> sampleVec = {1, 1, 3, 4};
for (int i = 0; i < sampleVec.size(); i++) {
std::cout << sampleVec.at(i) << " ";
}
std::cout << std::endl;
sampleVec.at(1) = 2;
for (int i = 0; i < sampleVec.size(); i++) {
std::cout << sampleVec.at(i) << " ";
}
std::cout << std::endl;
return 0;
}
Output:
1 1 3 4
1 2 3 4