将值从一个向量复制到另一个向量(从书中)

时间:2013-05-16 20:50:29

标签: c++

考虑这段代码。

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

问题的陈述是:

“鉴于此代码,请回答以下问题:

  1. 为什么“test”向量只包含2个?

  2. 我们如何才能更改for循环以正确复制(只有for循环中的代码)?“

  3. 我无法回答任何这些问题,所以我们将不胜感激。

    提前致谢。

4 个答案:

答案 0 :(得分:4)

该代码引入了悬空指针。循环体看起来像这样:

{
    int n = *v[i];
    test.push_back (&n);
}

局部变量n一旦循环体结束就会失去作用域,因此指针&n现在是一个悬空指针。如果test只包含2个,那就是随机出现的未定义行为

如果您想“正确”将数据复制到test,您可以将for循环体更改为:

{
    int* n = new int;
    *n = *v[i];
    test.push_back (n);
}

请带上一粒盐“正确”......

答案 1 :(得分:1)

第一个问题是一个技巧问题:向量包含指向不再存在的变量的指针,并且取消引用可能会导致几乎任何输出。我想在一些机器和编译器上它会打印所有2

我无法理解练习是做什么的(例如为什么它使用指针向量)所以我无法真正帮助解决问题。

你可以做到的一种方法是按值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这些指针,存在按值存储的问题。

答案 2 :(得分:1)

将两个相同的指针推送到ntest数组。 n等于第一个数组的最后一个元素。请注意,在控制流退出循环后,所有指向n的指针都将变为无效。所以,实际上你的test数组包含无效指针,而不是指向2的指针。

您应该创建每个整数的副本:

int* n = new int(*v[i]);
test.push_back (n);

另请注意,此处有内存泄漏。使用new创建的每个int应该稍后使用delete销毁。

答案 3 :(得分:0)

1)我认为这个问题的前提是错误的。循环向test添加两个元素,每个元素包含自动变量n的地址,其范围仅限于循环体。不保证n在两次传递循环中都会被分配相同的内存位置,但我认为大多数编译器可能会在两次传递中重用相同的位置。

此外,n超出了输出语句的范围。因此,未定义将test中的指针引用到那些内存位置。同样,它们很可能仍然包含循环中指定的值。

因此,只有在循环的第二次传递中同一位置被重用n并且在执行输出语句时该位置未被覆盖时,输出才是“2 2”。这些场所都不能保证。

2)要获得输出“1 2”而不改变循环外的任何内容,可以将n的定义更改为int& n = *v[i],这将是给定代码的单个字符更改,虽然最终的结果很奇怪。

更简单的解决方案是消除临时ntest.push_back(v[i])

相关问题