变量作为参考不停留

问题描述 投票:0回答:2

我读过这个帖子和许多其他帖子: 函数不会更改传递的指针 C++

但我仍然无法解决我的问题。 我有一个这样声明的函数:

void test(list<int*> *listNodes){
    int v=5;
    (*listNodes).push_back(&v);
    (*listNodes).push_back(&v);
    (*listNodes).push_back(&v);
    for(int a = 0; a < (*listNodes).size(); a ++){
        std::list<int*>::iterator i = (*listNodes).begin();
        advance(i, a);
        int *totry = *i;
        cout << *totry;
        cout << ",";
    }
}

这有效,并且打印得很好,我的意思是:listNodes 变量有 3 个元素,全是 5。但是,当该函数返回时,这些值不会更新。我的意思是该变量有垃圾。我在另一个函数中这样调用这个函数:

void create(list<int*> listNodes){
    test(&listNodes);
    for(list<int*>::const_iterator it=listNodes.begin();
     it!=listNodes.end(); it++){
        int *show=*it;
        cout << *show << '\n';
    }
}

同样,在这个函数中,cout 将输出内存垃圾,而不是输出 3 个五。 当功能测试返回时,我应该如何继续,我已经填充了列表,有什么想法吗?

c++ variables reference
2个回答
1
投票

我相信您正在考虑的问题(与此代码中的其他问题相反)实际上并不是您正在考虑的问题。 该列表确实维护其值,问题是它所具有的值指向垃圾内存。

当你这样做时:

int v=5;
(*listNodes).push_back(&v);
(*listNodes).push_back(&v);
(*listNodes).push_back(&v);

您将 v 地址的三个副本放入列表中。 您已将 v 声明为仅在此函数持续时间内存在的堆栈变量。 当您打印

function test
内的 listNodes 元素指向的值时,该变量仍然存在于该内存位置中。

当您稍后打印出

function create
中 listNodes 的元素指向的值时,该变量已超出范围并已被其他对象使用,因此是垃圾。

这里有两种可能的解决方案可供考虑:

  1. 使用
    list<int>
    而不是
    list<int *>
    。 如果您只想存储整数列表,那么这就是正确的方法。
  2. 另一方面,如果您确实需要存储指向这些整数的指针,则需要从堆中分配内存:

    int* v = new int(); // allocate an int on the heap
    *v = 5;             // store 5 in that int
    (*listNodes).push_back(v);  // save the pointer to the allocated
                                // memory in *listNodes
    etc
    

然而,就现代 C++ 而言,这并不是很好,因为您通常根本不想处理原始指针,但它说明了我认为您正在努力解决的问题。


0
投票

在此代码中,

void create(list<int*> listNodes){
    listNodes=teste(&listNodes);

…正式参数

listNodes
是按值传递的。这意味着该函数接收在调用系统中作为实际参数传递的任何内容的“副本”。对此副本的更改不会反映在实际参数中。

teste

的调用不会调用

test
函数,因为它是一个不同的名称。

在某种程度上这是好的,因为

test

被声明为

void
函数,因此它不能返回任何内容。

但这也很糟糕,因为这意味着您的代码中非常重要的一部分,即实际调用的

teste

函数,根本没有显示在您的问题中。



test

功能,


void test(list<int*> *listNodes){ int v=5; (*listNodes).push_back(&v); for(int a = 0; a < (*listNodes).size(); a ++){ std::list<int*>::iterator i = (*listNodes).begin(); advance(i, a); int *totry = *i; cout << *totry; cout << ","; } printf("\n"); }

…有很多问题。

从顶部开始,C++ 中的指针参数

void test(list<int*> *listNodes){

…最好是一个按引用传递的参数。指针可以为空。这对于这个函数来说没有意义,并且代码还没有准备好处理这个问题。

接下来,在

int v=5; (*listNodes).push_back(&v);

…局部变量的地址被推送到返回的列表上。但到那时,局部变量不再存在,并且你有一个“悬空指针”,它曾经指向某个东西,但现在不再指向了。如果调用者使用该指针,那么您就有未定义的行为。

接下来,这个循环, for(int a = 0; a < (*listNodes).size(); a ++){ std::list<int*>::iterator i = (*listNodes).begin(); advance(i, a);

…会起作用,但它不必要地具有 O(n

2
) 复杂度,即执行时间。

只需使用迭代器进行迭代即可。这就是迭代器的用途。迭代。

总结一下,你看到的垃圾是由于未定义的行为造成的。

只是,不要这样做。

© www.soinside.com 2019 - 2024. All rights reserved.