valarray 物件以序列的方式儲存其中的元素。像之前說的那樣,通過使用下標運算子來使用索引可以得到任何元素的參照,並能夠獲取或設定值。下面是一些範例:
std::valarray<int> data {1,2,3,4,5,6,7,8,9};
data[1] = data[2] + data[3]; // Data[1] is 7
data[3] *= 2; // Data[3] is 8
data[4] = ++data[5] - data[2];// data[4] is 4, data[5] is 7
這就像存取一般陣列的元素一樣。但是,valarray 物件的下標運算子有更多用處。可以用有下標運算子的輔助類的範例來代替索引。這使我們能夠指定和存取元素的子集。輔助類定義的元素選擇機制使它們可以用於元素,只要這些元素所在的陣列是二維或更多維數的陣列。理解這是如何工作的很重要,因為這是 valarray 超越序列容器的主要優勢。
還有很多細節,因此讓我們先看看大致的流程。我們首先會探討元素選擇機制一般是如何工作的,然後如何從二維陣列中選擇特定的行或列。會解釋如何將輔助類用於 valarray 物件以不同方式選擇的元素子集上,以及如何表示子集。在說明生成子集的各種可能方式之後,會討論能對它們做些什麼。在這之後,會展示如何將這些技術運用到應用的場景中。
建立切片
std::slice 類定義在 valarray 標頭檔案中。由傳給 valarray 物件的下標運算子的 slice 物件定義的 slice 就像索引。可以用 slice 物件作為 valarray 物件的下標來選擇兩個或更多個元素。被選擇的元素不需要是陣列中的連續元素。slice 選擇的陣列元素可以作為參照,因此可以存取或改變這些元素的值。
從根本上說,slice 物件為從 valarray 選擇的元素封裝了一系列索引。可以將 3 個 size_t 型別的值傳給 slice 建構函式來定義 slice 物件:
-
valarray 物件中的 start index (起始索引)指定了子集的第一個元素;
-
size 是子集中的元素個數;
-
stride (步進)是為從子集中得到下一個元素的 valarray 索引的增量;
建構函式的引數釆用描述的順序,因此可以按如下方式定義 slice 物件:
slice my_slice {3, 4, 2}; // start index = 3, size = 4, stride = 2
這個物件指定了從索引 3 開始的 4 個元素,後續索引的增量為 2。也有建構函式,因此可以複製進行 slice 物件。預設的建構函式會將 start index、size 和 stride 全部設為 0,它的唯一目的是進行切片物件陣列的建立。
可以呼叫 slice 物件的成員函數 start() 來得到它的 start index。slice 物件也有成員函數 size() 和 stride(),它們各自返回 size 和 stride。返回的 3 個值都是 size_t 型別。
通常,在使用 slice{start,size, stride} 物件作為 valarray 物件的下標時,可以選擇索引值位置的元素:
start, start + stride, start + 2*stride,...start + (size - 1)*stride
圖 1 用一個值從 1 到 15 的 valarray 物件進行了展示。
圖 1 slice 物件選擇的 valarray 中的元素子集