我读过这个帖子和许多其他帖子: 函数不会更改传递的指针 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 个五。 当功能测试返回时,我应该如何继续,我已经填充了列表,有什么想法吗?
我相信您正在考虑的问题(与此代码中的其他问题相反)实际上并不是您正在考虑的问题。 该列表确实维护其值,问题是它所具有的值指向垃圾内存。
当你这样做时:
int v=5;
(*listNodes).push_back(&v);
(*listNodes).push_back(&v);
(*listNodes).push_back(&v);
您将 v 地址的三个副本放入列表中。 您已将 v 声明为仅在此函数持续时间内存在的堆栈变量。 当您打印
function test
内的 listNodes 元素指向的值时,该变量仍然存在于该内存位置中。
当您稍后打印出
function create
中 listNodes 的元素指向的值时,该变量已超出范围并已被其他对象使用,因此是垃圾。
这里有两种可能的解决方案可供考虑:
list<int>
而不是 list<int *>
。 如果您只想存储整数列表,那么这就是正确的方法。 另一方面,如果您确实需要存储指向这些整数的指针,则需要从堆中分配内存:
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(n
2) 复杂度,即执行时间。
只需使用迭代器进行迭代即可。这就是迭代器的用途。迭代。
总结一下,你看到的垃圾是由于未定义的行为造成的。只是,不要这样做。