变量作为参考不保留

Variable as reference not staying

本文关键字:保留 参考 变量      更新时间:2023-10-16

所以我读了这个帖子和许多其他帖子:函数不改变传递的指针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个5。关于我应该如何继续,当功能测试回来,我有列表填充的想法吗?

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

当你这样做的时候:

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++来说,这并不是很好,因为您通常根本不想处理原始指针,但它说明了我认为您正在努力解决的问题。

在此代码中,

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(n2)复杂度,即执行时间。

只使用迭代器进行迭代。这就是迭代器的作用。迭代。


总而言之,你看到的垃圾是由于未定义的行为。

别那么做