简体   繁体   English

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

[英]Copying values from one vector to another (from book)

Consider this piece of code. 考虑这段代码。

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

The problem's statement is: 问题的陈述是:

"Given this code, answer the following questions: “鉴于此代码,请回答以下问题:

  1. Why does "test" vector contain only 2's? 为什么“测试”向量仅包含2?

  2. How can we change for loop to copy properly (only code inside for loop)?" 我们如何更改for循环以正确复制(仅for循环内的代码)?”

I couldn't answer any of these questions, so a little bit of help will be appreciated. 我无法回答任何这些问题,因此将不胜感激。

Thanks in advance. 提前致谢。

That code introduces dangling pointers. 该代码引入了悬空指针。 The body of the loop looks like this: 循环的主体如下所示:

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

The local variable n loses scope as soon as the loop body ends, so the pointer &n is now a dangling pointer. 循环体结束时,局部变量n失去作用域,因此指针&n现在是悬空指针。 If it happens that test contains only 2's, that's just what randomly came out of what is undefined behavior . 如果碰巧test仅包含2,那就是从未定义行为中随机产生的结果

If you want to "properly" copy the data over to test , you can change the for loop body to this: 如果要“正确”复制数据以进行test ,可以将for循环体更改for

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

Please take the "properly" with a grain of salt... 请“适量”加一粒盐。

The first question is a trick question: The vector contains pointers to a variable that no longer exists, and dereferencing that could cause pretty much any output. 第一个问题是一个技巧性的问题:向量包含指向不再存在的变量的指针,并且取消引用可能会导致几乎任何输出。 I imagine on some machines and compilers it prints all 2 s however. 我想在某些机器和编译器上它会打印所有2 s。

I can't understand what the exercise is trying to do (why does it use vectors of pointers for example) so I can't really help with how to solve the problem. 我不明白该练习正在尝试做什么(例如,为什么要使用指针向量),所以我无法真正帮助解决问题。

One way you could do it is by making test store by value: 一种方法是按值存储test

First change the test vector to vector <int> test; 首先将测试向量更改为vector <int> test;

Then change the push_back to something like test.push_back (n); 然后将push_back更改为test.push_back (n); and finally the print statements to remove the now-unneeded * operators. 最后是print语句,以删除现在不需要的*运算符。

EDIT for comment: 编辑评论:

First, I'm suspect of this book: It shouldn't be demonstrating undefined behavior or raw pointers to single builtin types. 首先,我怀疑这本书:它不应该显示未定义的行为或指向单个内置类型的原始指针。 But you can change your loop body if you want: 但是,您可以根据需要更改循环主体:

 for (int i = 0; i < 2; ++i)
 {
     int* n = new int;
    *n = *v[i];
     test.push_back (&n);
 }

Note that both this will cause a memory leak unless you later delete those pointers, a problem that storing by value eliminates. 请注意,除非您以后delete这些指针,否则这两种情况都会导致内存泄漏,从而消除了按值存储的问题。

You push two the same pointers to n into test array. 您将两个相同的指针推到ntest数组中。 n equals the last element of your first array. n等于第一个数组的最后一个元素。 Note that after control flow exited the loop, all pointers to n become invalid. 请注意,控制流退出循环后,所有指向n指针都将变为无效。 So, in fact your test array contains invalid pointers, not pointers to 2s. 因此,实际上您的test数组包含无效的指针,而不是指向2s的指针。

You should create a copy of each integer: 您应该为每个整数创建一个副本:

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

Note also that you have memory leak here. 另请注意,此处内存泄漏。 Each int created using new should be later destroyed using delete . 使用new创建的每个int都应在以后使用delete销毁。

1) I think that the premise of the question is faulty. 1)我认为问题的前提是错误的。 The loop adds two elements to test , each contains the address of the automatic variable n , the scope of which is limited to the body of the loop. 循环添加了两个要test元素,每个元素都包含自动变量n的地址,其范围限于循环的主体。 It's not guaranteed that n will be allocated the same memory location in both passes through the loop, but I suppose that it's likely that most compilers will reuse the same location in both passes. 不能保证在两次循环中都将为n分配相同的内存位置,但是我想大多数编译器可能会在两次循环中重用相同的位置。

Moreover, n is out of scope at the output statement. 此外, n在输出语句之外。 So referencing the pointers in test to those memory locations is undefined. 因此,未定义将test的指针引用到那些内存位置。 Again, there's a good chance that they will still contain the values assigned in the loop. 同样,很有可能它们仍将包含循环中分配的值。

So, only if the same location gets reused for n in the second pass of the loop and that location has not been overwritten at the time the output statement is executed, will the output be "2 2". 因此,仅当在循环的第二遍中将相同的位置重用n在执行输出语句时该位置未被覆盖时,输出才为“ 2 2”。 There is no guarantee of either of these premises. 这两个场所均无法保证。

2) To get the output "1 2" without changing anything outside the loop, one could change the definition of n to int& n = *v[i] , which would be a single character change from the given code, though the end result is rather strange. 2)要获得输出“ 1 2”而不在循环外进行任何更改,可以将n的定义更改为int& n = *v[i] ,尽管最终结果是给定代码的单个字符更改有点奇怪

A simpler solution would be to eliminate the temporary n and simply test.push_back(v[i]) . 一个更简单的解决方案是消除临时n并只需test.push_back(v[i])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM