分配给数组 std::vector 中的 std::array 元素失败
Assigning to std::array element in std::vector of arrays fails
今天,我正在努力了解一些新功能,尤其是 std::array
和 std::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));
我想做的事情可能很明显,但如果有帮助,我会用散文写出来:
松散地,我正在创建一个整数数组向量。在示例的前半部分,我为这些数组创建了一个 pointers 的向量,并且能够通过指针插入一个新数组,然后修改该数组中包含的元素.下半场,我尽量避免使用指针。该代码似乎成功插入了数组,但不允许我更改其中的元素。
令我有些惊讶的是,无论是在编译时还是在运行时,警告或错误为零,我猜我遗漏了一些基本的东西;有人能指出我正确的方向吗?
您正在处理数组的副本,您需要在向量中引用数组
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
) – 经过适当的修改 – 将多个(不同的)数组推送到您的向量中。
但是,在第二种情况下,该副本几乎可以肯定不是您想要的。相反,您应该声明一个 reference variable 并将其分配给您要修改的向量的元素。
在您的代码中显示的简单情况下,用法如下:
//...
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 数组的副本替换之前的 referred-to 元素)。值得注意的 'exception' 是在 range-based for
循环中使用这样的引用变量时,如下所示:
for (auto& vals : va) {
vals[0] = 42; // This will refer to a different "va" element each loop
}
类似地,您可以在更传统的 for
循环(或者,实际上,在任何循环或 block-scope );这将有效地在每次迭代循环时创建一个新引用(实际上,这也是上面所做的,range-based 循环)。因此,此代码会将每个数组的第一个元素设置为循环的 i
索引:
for (size_t i = 0; i < va.size(); ++i) {
auto& vals = va.at(i);
vals[0] = static_cast<int>(i);
}
今天,我正在努力了解一些新功能,尤其是 std::array
和 std::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));
我想做的事情可能很明显,但如果有帮助,我会用散文写出来:
松散地,我正在创建一个整数数组向量。在示例的前半部分,我为这些数组创建了一个 pointers 的向量,并且能够通过指针插入一个新数组,然后修改该数组中包含的元素.下半场,我尽量避免使用指针。该代码似乎成功插入了数组,但不允许我更改其中的元素。
令我有些惊讶的是,无论是在编译时还是在运行时,警告或错误为零,我猜我遗漏了一些基本的东西;有人能指出我正确的方向吗?
您正在处理数组的副本,您需要在向量中引用数组
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
) – 经过适当的修改 – 将多个(不同的)数组推送到您的向量中。
但是,在第二种情况下,该副本几乎可以肯定不是您想要的。相反,您应该声明一个 reference variable 并将其分配给您要修改的向量的元素。
在您的代码中显示的简单情况下,用法如下:
//...
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 数组的副本替换之前的 referred-to 元素)。值得注意的 'exception' 是在 range-based for
循环中使用这样的引用变量时,如下所示:
for (auto& vals : va) {
vals[0] = 42; // This will refer to a different "va" element each loop
}
类似地,您可以在更传统的 for
循环(或者,实际上,在任何循环或 block-scope );这将有效地在每次迭代循环时创建一个新引用(实际上,这也是上面所做的,range-based 循环)。因此,此代码会将每个数组的第一个元素设置为循环的 i
索引:
for (size_t i = 0; i < va.size(); ++i) {
auto& vals = va.at(i);
vals[0] = static_cast<int>(i);
}