簡體   English   中英

分配給 std::array 數組中的 std::array 元素失敗

[英]Assigning to std::array element in std::vector of arrays fails

今天,我正在努力理解一些對我來說很新的特性,特別是std::arraystd::vector 單獨來看,這些行為似乎符合預期,但我對下面所示的行為感到非常困惑:

此版本有效:

printf("Using pointer:\n");
std::vector<std::array<int, 1>*> vap;
vap.push_back(new std::array<int, 1>());
printf("size of vector is %ld\n", vap.size());

printf("before setting value:\n");
printf("value is %d\n", vap.front()->at(0));
std::array<int, 1>* pvals = vap.front();
pvals->at(0) = -1;
printf("after setting value:\n");
printf("value is %d\n", vap.front()->at(0));

此版本不更新數組:

printf("Without pointer:\n");
std::vector<std::array<int, 1>> va;
std::array<int, 1> arr = {99};
va.push_back(arr);

像這樣插入數組也會失敗: va.push_back(std::array<int, 1>());

printf("size of vector is %ld\n", va.size());

printf("before setting value:\n");
printf("value is %d\n", va.front().at(0));
std::array<int, 1> vals = va.front();
vals[0] = -1;
printf("after setting value:\n");
printf("value is %d\n", va.front().at(0));

我正在嘗試做的事情可能很明顯,但如果有幫助,我會用散文寫出來:

松散地,我正在創建一個整數數組的向量。 在示例的前半部分,我創建了一個指向這些數組的指針向量,並且能夠通過指針插入一個新數組,然后修改該數組中包含的元素。 在下半場,我盡量避免使用指針。 該代碼似乎成功插入了數組,但隨后不允許我更改其中的元素。

我有點驚訝於在編譯或運行時出現零警告或錯誤,我猜我錯過了一些基本的東西。 接下來我可以嘗試什么?

您正在處理數組的副本,您需要對向量中的數組的引用

int main() {
    vector<array<int, 1>> v;
    array<int, 1> a = { 99 };
    v.push_back(a);
    cout << v[0][0];
    auto& ar = v[0];
    ar[0] = 42;
    cout << v[0][0];
}

 99 42

你的va.push_back(arr); std::array<int, 1> vals = va.front(); 語句正在復制其源操作數。 因此,對這些副本所做的任何更改都不會影響源數組。

push_back的情況下,這可能是您想要的,因此您可以(例如)使用相同的源變量( arr )——經過適當的修改——將多個(不同的)數組推送到你的向量中。

但是,在第二種情況下,該副本幾乎肯定不是您想要的。 相反,您應該聲明一個引用變量並將其分配給您要修改的向量的元素。

在您在代碼中顯示的簡單情況下,用法如下:

//...
std::array<int, 1>& vals = va.front(); // The "&" declares a reference
vals[0] = -1; // This now modifies the (element of the) array referred to.

但是請注意,在引用變量被聲明和初始化為引用特定源之后,您不能重新分配它; 因此,隨后的vals = va.at(2); 不會像你想的那樣做(事實上,它會用 RHS 數組的副本替換之前提到的元素)。 一個值得注意的“例外”是在基於范圍的for循環中使用此類引用變量時,如下所示:

for (auto& vals : va) {
   vals[0] = 42; // This will refer to a different "va" element each loop
}

類似地,您可以在更傳統for循環內(或者,事實上,在任何循環或塊范圍內)顯式定義這樣的引用; 這將有效地在每次迭代循環時創建一個新引用(實際上,這也是上述基於范圍的循環中所做的)。 因此,這段代碼會將每個數組的第一個元素設置為循環的i索引:

for (size_t i = 0; i < va.size(); ++i) {
    auto& vals = va.at(i);
    vals[0] = static_cast<int>(i);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM