[]
在 C++ 裡面被稱為「subscript operator」,最常使用的情境應該是用來存取資料;尤其在陣列形式的資料中,大部分的人應該都很習慣這樣存取資料了~下面就是一個簡單的使用示意:
std::array<int, 3> a = { 1,2,3 }; a[2] = 4;
這樣的使用實際上就是去呼叫他的 array subscript operator(參考)。
不過,到 C++20 為止,這個運算子都只能接受一個值作為函式引數、所以其實在要存取多維度資料的時候,其實不是很方便。
以一個矩陣來說好了,這邊可能可以定義成:
template<typename T, size_t W, size_t H> class CMatrix { public: template<typename ... TI> CMatrix(const TI&&... vals) : m_aData{ vals ... } {} T& data(size_t x, size_t y) { return m_aData[x + y * W]; } protected: std::array<T, W * H> m_aData; };
在這樣的定義下,要存取矩陣裡的其中一項、則可以透過 data()
這個函式來做到:
CMatrix<float, 3, 2> m = { 1.0f,2.0f,3.0f, 4.0f,5.0f,6.0f }; std::cout << m.data(0, 1) << "\n";
但是由於 operator[]
只能支援一個引數,所以並沒有辦法寫成 m[0,1]
這樣類似存取陣列的形式。
當然,這邊也是可以透過 operator()
來實作,但是在語意上其實比較容易搞混就是了。
而到了 C++23 則是引進了「multidimensional subscript operator」(P2128R6)、放寬了對於 operator[]
的限制。
所以,在支援這項功能的環境中(目前 Visual C++ 不支援、但是 g+12 已經支援了),就可以改寫成:
template<typename T, size_t W, size_t H> class CMatrix { public: template<typename ... TI> CMatrix(const TI&&... vals) : m_aData{ vals ... } {} T& operator[](size_t x, size_t y) { return m_aData[x + y * W]; } protected: std::array<T, W * H> m_aData; };
如此一來,存取這個矩陣的資料,就可以使用 m[0,1]
這樣的形式了。
基本上,這項核心語言上的改變、對於功能面上並沒有明顯的影響,畢竟本來就可以透過其他名稱的函式來實作。
但是這樣的修改可以讓多維陣列的存取和一維陣列更有一致性,在語意上會更明確。
而當然也會希望以後會都統一支援這樣的存取定義,在使用上會更方便。
這邊另外補充一下,以前的 C++ 標準裡面,在 []
裡面其實是可以有「,
」的;只是它實際上是作為「comma operator」在運作、會把左邊的結果略過去、只回傳最後的結果。
所以如果寫 a[0,1]
的話、實際上 0 會被無視、變成 a[1]
。
而到了 C++20,這樣的寫法也被標記成廢棄、在編譯時會吐警告了。
最後,算是對應這個修改,C++23 在標準函示庫中也加入了 std::span
的多維度版本、std::mdspan
(參考)。
透過 std::mdspan
、可以相當簡單地將一維陣列包裝成多維度的陣列來存取。不過比較可惜的,是目前這東西還沒有哪個編譯器能完整支援就是。