[英]Copying values from one vector to another (from book)
考虑这段代码。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <int *> test;
vector <int *> v;
int *a = new int;
int *b = new int;
*a = 1;
*b = 2;
v.push_back (a);
v.push_back (b);
for (int i = 0; i < 2; ++i)
{
int n = *v[i];
test.push_back (&n);
}
cout << *test[0] << " " << *test[1] << endl;
delete a;
delete b;
return 0;
}
问题的陈述是:
“鉴于此代码,请回答以下问题:
为什么“测试”向量仅包含2?
我们如何更改for循环以正确复制(仅for循环内的代码)?”
我无法回答任何这些问题,因此将不胜感激。
提前致谢。
该代码引入了悬空指针。 循环的主体如下所示:
{
int n = *v[i];
test.push_back (&n);
}
循环体结束时,局部变量n
失去作用域,因此指针&n
现在是悬空指针。 如果碰巧test
仅包含2,那就是从未定义行为中随机产生的结果 。
如果要“正确”复制数据以进行test
,可以将for
循环体更改for
:
{
int* n = new int;
*n = *v[i];
test.push_back (n);
}
请“适量”加一粒盐。
第一个问题是一个技巧性的问题:向量包含指向不再存在的变量的指针,并且取消引用可能会导致几乎任何输出。 我想在某些机器和编译器上它会打印所有2
s。
我不明白该练习正在尝试做什么(例如,为什么要使用指针向量),所以我无法真正帮助解决问题。
一种方法是按值存储test
:
首先将测试向量更改为vector <int> test;
然后将push_back更改为test.push_back (n);
最后是print语句,以删除现在不需要的*
运算符。
编辑评论:
首先,我怀疑这本书:它不应该显示未定义的行为或指向单个内置类型的原始指针。 但是,您可以根据需要更改循环主体:
for (int i = 0; i < 2; ++i)
{
int* n = new int;
*n = *v[i];
test.push_back (&n);
}
请注意,除非您以后delete
这些指针,否则这两种情况都会导致内存泄漏,从而消除了按值存储的问题。
您将两个相同的指针推到n
到test
数组中。 n
等于第一个数组的最后一个元素。 请注意,控制流退出循环后,所有指向n
指针都将变为无效。 因此,实际上您的test
数组包含无效的指针,而不是指向2s的指针。
您应该为每个整数创建一个副本:
int* n = new int(*v[i]);
test.push_back (n);
另请注意,此处内存泄漏。 使用new
创建的每个int都应在以后使用delete
销毁。
1)我认为问题的前提是错误的。 循环添加了两个要test
元素,每个元素都包含自动变量n
的地址,其范围限于循环的主体。 不能保证在两次循环中都将为n
分配相同的内存位置,但是我想大多数编译器可能会在两次循环中重用相同的位置。
此外, n
在输出语句之外。 因此,未定义将test
的指针引用到那些内存位置。 同样,很有可能它们仍将包含循环中分配的值。
因此,仅当在循环的第二遍中将相同的位置重用n
在执行输出语句时该位置未被覆盖时,输出才为“ 2 2”。 这两个场所均无法保证。
2)要获得输出“ 1 2”而不在循环外进行任何更改,可以将n
的定义更改为int& n = *v[i]
,尽管最终结果是给定代码的单个字符更改有点奇怪
一个更简单的解决方案是消除临时n
并只需test.push_back(v[i])
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.