简体   繁体   English

分配给 std::array 数组中的 std::array 元素失败

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

Today, I'm working on understanding some new-to-me features, particularly std::array and std::vector .今天,我正在努力理解一些对我来说很新的特性,特别是std::arraystd::vector Individually, these seem to behave as expected, but I'm very puzzled by the behavior illustrated below:单独来看,这些行为似乎符合预期,但我对下面所示的行为感到非常困惑:

This version works:此版本有效:

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));

This version doesn't update the array:此版本不更新数组:

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

Inserting the array like this fails too: va.push_back(std::array<int, 1>());像这样插入数组也会失败: 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));

It's likely obvious what I'm trying to do but, in case it helps, I'll write it in prose:我正在尝试做的事情可能很明显,但如果有帮助,我会用散文写出来:

Loosely, I'm creating a vector of arrays of ints.松散地,我正在创建一个整数数组的向量。 In the first half of the example, I create a vector of pointers to those arrays, and am able to insert a new array, via a pointer, and then modify the element contained in that array.在示例的前半部分,我创建了一个指向这些数组的指针向量,并且能够通过指针插入一个新数组,然后修改该数组中包含的元素。 In the second half, I tried to avoid using pointers.在下半场,我尽量避免使用指针。 That code seems to insert the array successfully but then does not allow me to alter the element within it.该代码似乎成功插入了数组,但随后不允许我更改其中的元素。

I'm somewhat surprised that there are zero warnings or errors, either at compile or runtime, and I'm guessing that I'm missing something fundamental.我有点惊讶于在编译或运行时出现零警告或错误,我猜我错过了一些基本的东西。 What can I try next?接下来我可以尝试什么?

You are working on a copy of the array, you need a reference to the array in the vector您正在处理数组的副本,您需要对向量中的数组的引用

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];
}

gives

 99 42

Both your va.push_back(arr);你的va.push_back(arr); and std::array<int, 1> vals = va.front();std::array<int, 1> vals = va.front(); statements are making copies of their source operands.语句正在复制其源操作数。 Thus, any changes made to those copies won't affect the source arrays.因此,对这些副本所做的任何更改都不会影响源数组。

In the case of the push_back , this is possibly what you want, so that you can (for example) use the same source variable ( arr ) – after suitable modifications – to push multiple (different) arrays into your vector.push_back的情况下,这可能是您想要的,因此您可以(例如)使用相同的源变量( arr )——经过适当的修改——将多个(不同的)数组推送到你的向量中。

However, in the second case, that copy is almost certainly not what you want.但是,在第二种情况下,该副本几乎肯定不是您想要的。 Instead, you should declare a reference variable and assign that to the element of the vector you want to modify.相反,您应该声明一个引用变量并将其分配给您要修改的向量的元素。

In the trivial case that your have shown in your code, the usage would be as follows:在您在代码中显示的简单情况下,用法如下:

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

But note, you can't reassign a reference variable after it has been declared and initialized as referring to a particular source;但是请注意,在引用变量被声明和初始化为引用特定源之后,您不能重新分配它; thus, a subsequent vals = va.at(2);因此,随后的vals = va.at(2); would not do what you might think (it will, in fact, replace the previously referred-to element with a copy of the RHS array).不会像你想的那样做(事实上,它会用 RHS 数组的副本替换之前提到的元素)。 A notable 'exception' to this is when using such a reference variable in a range-based for loop, like this:一个值得注意的“例外”是在基于范围的for循环中使用此类引用变量时,如下所示:

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

You can, similarly, define such a reference explicitly inside a more traditional for loop (or, in fact, in any loop or block-scope);类似地,您可以在更传统for循环内(或者,事实上,在任何循环或块范围内)显式定义这样的引用; that will, effectively, create a new reference each time the loop is iterated (actually, this is also what is being done in the above, range-based loop).这将有效地在每次迭代循环时创建一个新引用(实际上,这也是上述基于范围的循环中所做的)。 So, this code will set the first element of each array to the loop's i index:因此,这段代码会将每个数组的第一个元素设置为循环的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