Search code examples
c++stdvector

Why isn't std::vector::at a const function?


I'm trying to implement std::vector but I encountered the question. According to C++ reference, std::vector::at is like:

      reference at (size_type n);
const_reference at (size_type n) const;

My question is: Why don't I use reference at (size_type n) const;?

Thank you for any help or criticism!


Update: Thanks! I'm clear about that.

My fault is that I don't konw functions with and without const are also a kind of overload. The original design is to use the one with const when a const vector calls it, so it'll return a const_reference. When a vector which is not const, then the return value shouldn't be const_reference.

But if we make the 2 functions both const, then the 2 functions will have no differences except for the return type which is not a legal override. So the former one is not designed to be const though it can be const.

Thanks!


Solution

  • Think about the issue that a ref at (size_type n) const; could cause. First of all, you need to understand why const_reference at (size_type n) const; exists. In a const std::vector, once it is initialized, it or its elements are not supposed to be changed (because it is, after all, const). The normal reference at (size_type n); will not work for a const vector, because it returns a non-const reference to an element, meaning it can be changed. This goes against the idea of consting your object, which is why this specific overload would not work for a const vector.

    This is where const_reference at (size_type n) const; comes in. As you may know, the end const is a promise to the compiler and the programmer that this will not change its object or provide the opportunity for its object to be changed, so it can be used with a const object. In the case of const_reference at (size_type n) const;, this is indeed true: it returns a const reference, meaning the element you get cannot be changed. This guarantees that your const vector is indeed const and it will not be changed.

    This is why reference at (size_type n) const; is a problem. You're lying to both the compiler and the programmer by saying that this is safe to use on a const object, where in fact it is indeed not, because since it returns a mutable reference, you can easily change the element you get with at.

    Just ask yourself: wouldn't you be shocked if this program worked?

    #include <vector>
    
    int main()
    {
        const std::vector<int> a = {1, 2, 3};
        a.at(0) = 10;
    }