Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::array's data member is public in a standard library implementation. Why?

Tags:

c++

std

I was trying to study standard library implementation of the containers that are part of the C++ standard library. I have Microsoft Visual Studio 2022 on my machine and I could go to the header file definition of std::array class.

While I reached the end of the class definition of std::array class, I noticed that the data member is not declared private and above it were all the public member functions, so that make the data member public as well.

So to test it, I tried to access it in my std::array object defined in main() and to my surprise I could access it and it printed the proper value in the output too!

#include <array>
#include <iostream>
int main() 
{
    std::array<int, 5> staticArray{0,1,2,3,4};
    std::cout << staticArray._Elems[1] << std::endl;
}

Is this allowed?! Anybody can corrupt the data, right?

like image 966
ZoomIn Avatar asked Nov 23 '25 17:11

ZoomIn


2 Answers

It is required that std::array have a public member to satisfy the requirement that std::array be an aggregate.

An array is an aggregate that can be list-initialized with up to N elements whose types are convertible to T.

https://eel.is/c++draft/array#overview-2

It doesn't however specify what the public member should be named, since the only requirement is that it is an aggregate that can be list-initialized.

_Elems won't necessarily be compatible with other standard library implementations.

With respect to your concern of anyone being able to corrupt the data, anyone can already do that via any of the mutable accessors: data(), operator[], etc

like image 85
mpark Avatar answered Nov 26 '25 11:11

mpark


Because it is not a modifiable lvalue, you cannot damage it by doing something like Array._Elems = nullptr;. Therefore, there is no need to protect it by making it private.

On the other hand, it provides a way to truly directly access the C-style array.

For example, if you use C++14 in Visual Studio 2022, due to operator[] being declared as inline instead of constexpr, the following constexpr function cannot be computed at compile time.

constexpr array<int, 100> f1() {
    array <int, 100> out{};
    for (int i = 0; i < 100; ++i) {
        out[i] = i;
    }
    return out;
}
constexpr auto abc = f1();//C2131 expression did not evaluate to a constant

However, using ._Elems can succeed.

constexpr array<int, 100> f2() {
    array <int, 100> out{};
    for (int i = 0; i < 100; ++i) {
        out._Elems[i] = i;
    }
    return out;
}
constexpr auto abc = f2();//OK

But since operator[] has been declared as constexpr since C++17, I can't think of any situation where you would need to directly access the internal C-style array for now.

like image 32
許恩嘉 Avatar answered Nov 26 '25 10:11

許恩嘉