为啥调用函数时指针会改变地址?

Posted

技术标签:

【中文标题】为啥调用函数时指针会改变地址?【英文标题】:Why does a pointer change address when I call a function?为什么调用函数时指针会改变地址? 【发布时间】:2021-03-18 04:42:44 【问题描述】:

我正在尝试用 C++ 实现一个链表。

int main() 
    ListaEnlazada <int> l1 (5);
    //l1.imprimir();
    l1.insertar(10, 0);
    l1.imprimir();


template<typename T>
class ListaEnlazada 
public:
    ListaEnlazada(T inicial) 
        cabeza = new Nodo <T> (inicial);
        tamano = 1;
    
    void insertar(const T &valor, size_t indice) 
        if(indice >= 0 && indice <= tamano) 
            Nodo <T> *nodo_previo = NULL;
            Nodo <T> *nodo_actual = cabeza;
            for(size_t i = 0; i < indice; i++) 
                nodo_previo = nodo_actual;
                nodo_actual = nodo_actual->obtener_siguiente();
                           
            Nodo <T> nuevo_nodo (valor);
            if(nodo_previo == NULL) 
                cabeza = &nuevo_nodo;
                nuevo_nodo.establecer_siguiente(nodo_actual);
                tamano += 1;
            
            else if(nodo_previo != NULL && nodo_actual != NULL) 
                nodo_previo->establecer_siguiente(&nuevo_nodo);
                nuevo_nodo.establecer_siguiente(nodo_actual);
                tamano += 1;
            
            else if(nodo_actual == NULL) 
                nodo_previo->establecer_siguiente(&nuevo_nodo);
                nuevo_nodo.establecer_siguiente(nodo_actual);
                tamano += 1;
            
            else 
                std::cout << "Error: ocurrió algo inesperado." << std::endl;
            
        
        else 
            std::cout << "Error: el índice máximo permitido actualmente es: " << tamano << "." << std::endl;
        
    
    void imprimir() 
        Nodo <T> *nodo_actual = cabeza;
        for(size_t i = 0; i < tamano; i++) 
            std::cout << nodo_actual->obtener_elemento() << " ";
            nodo_actual = nodo_actual->obtener_siguiente();
        
        std::cout << std::endl;
    
private:
    Nodo <T> *cabeza;
    size_t tamano;
;

template<typename T>
class Nodo 
public:
    Nodo(T elem) 
        elemento = elem;
        sig_elem = NULL;
    

    Nodo *obtener_siguiente() 
        return sig_elem;
    

    void establecer_siguiente(Nodo *sig_ptr) 
        sig_elem = sig_ptr;
    

    T obtener_elemento() 
        return elemento;
    
private:
    T elemento;
    Nodo <T> *sig_elem;
;

显然我的初始化和插入元素的功能工作正常。但是在程序执行打印函数之后,指向列表中第二个元素的指针立即改变了它指向的地址,并且第二个元素也改变了它的值。 我已经使用了调试模式,注意到在索引 0 处插入元素 10 后一切正常,但在程序执行打印功能后立即出现错误。

【问题讨论】:

在打印功能之后,你马上就要让你的头从堆栈上掉下来了。是否有您排除的代码?您能否更好地表明您如何知道事情正在发生变化? 我没有排除任何代码,除了标题。使用调试模式,我看到在进入打印函数之前,列表头部的sig_elem值为0x55555556aeb0,进入函数后,它的值为0x7fffffffdc50。它在程序结束时打印的值是 10 -962292416 而不是 10 5。 【参考方案1】:

这是你的问题:

    Nodo <T> nuevo_nodo (valor);
    if(nodo_previo == NULL) 
        cabeza = &nuevo_nodo;
        nuevo_nodo.establecer_siguiente(nodo_actual);
        tamano += 1;
    

这个变量只是坐在堆栈上。它会消失的。你可能真的需要在这里做一个new Nodo&lt;t&gt;

【讨论】:

【参考方案2】:

问题在于您的插入函数 - nuevo_nodo 被声明为局部变量。只要您在insertar 中,它似乎就可以正常运行,但是一旦您离开,您的新节点就会丢失并且头部指向垃圾数据。

将其更改为 new Nodo&lt;T&gt;(并在代码后面更改对它的引用)可以解决您的问题。

    void insertar(const T &valor, size_t indice) 
        if(indice >= 0 && indice <= tamano) 
            Nodo <T> *nodo_previo = NULL;
            Nodo <T> *nodo_actual = cabeza;
            for(size_t i = 0; i < indice; i++) 
                nodo_previo = nodo_actual;
                nodo_actual = nodo_actual->obtener_siguiente();
            
            Nodo <T> *nuevo_nodo = new Nodo<T>(valor);  //put it on the heap
            if(nodo_previo == NULL) 
                cabeza = nuevo_nodo;
                nuevo_nodo->establecer_siguiente(nodo_actual);
                tamano += 1;
            
            else if(nodo_previo != NULL && nodo_actual != NULL) 
                nodo_previo->establecer_siguiente(nuevo_nodo);
                nuevo_nodo->establecer_siguiente(nodo_actual);
                tamano += 1;
            
            else if(nodo_actual == NULL) 
                nodo_previo->establecer_siguiente(nuevo_nodo);
                nuevo_nodo->establecer_siguiente(nodo_actual);
                tamano += 1;
            
            else 
                std::cout << "Error: ocurrió algo inesperado." << std::endl;
            
        
        else 
            std::cout << "Error: el índice máximo permitido actualmente es: " << tamano << "." << std::endl;
        
    

【讨论】:

以上是关于为啥调用函数时指针会改变地址?的主要内容,如果未能解决你的问题,请参考以下文章

C语言基础:指针相关概念(指针的算术运算 指针数组指向指针的指针 传递指针给函数 从函数返回指针 )为啥C 语言不支持在调用函数时返回局部变量的地址?

OC(C语言特性函数,指针)

c语言 怎么解决调用函数导致的原数组改变

当函数返回时,指向超出范围的对象的 C++ 指针 - 为啥会这样?

为啥使用函数指针调用函数会绕过钩子?

调用函数时为啥形参的值不能传给实参