c++ 为什么值在离开函数后会改变,为什么会出现分段错误?

7eumitmz  于 2023-01-22  发布在  其他
关注(0)|答案(1)|浏览(114)

C++课我有这个作业,要实现一个list类,在那里我可以从前面或者后面添加,我已经实现了,但是有个大问题。
collectiontest.cpp

#include "list.hpp"
#include <iostream>

int main(void) {
    std::cout << "--- Test List ---" << std::endl;
    List<int> l;
    std::cout << l;
    l.add(2);
    l.add_front(3);
    l.add(1);
    std::cout << l;

    std::cout << "remove_front: " << l.remove_front() << std::endl;
    std::cout << "remove_front: " << l.remove_front() << std::endl;
    l.add(5);
    std::cout << l;
    std::cout << "Contains 5? " << l.contains(5) << std::endl;

    std::cout << "remove_back: " << std::endl;
    std::cout << l.remove() << std::endl;
    std::cout << "remove_back: " << l.remove() << std::endl;
    std::cout << l;
return 0;
}

list.hpp

#pragma once
#include "collection.hpp"
#include "node.hpp"
#include <iostream>
#include <string>

template <typename T>
class List : public Collection<T> {

private:
    Node<T>* first;
    Node<T>* last;

public:

   

    ~List() {
        if (first != nullptr) {

        }

    }

    void add_front(T value) {

        if (first == nullptr) {
            std::cout << "First element front" << std::endl;
            Node<T> temp(value, nullptr, nullptr);

            first = &temp;
            last = &temp;

        }
        else {

            if (first == last) {

                std::cout << "First and last are same! front-> " << first << "-" << last << std::endl;

                Node<T> temp(value, last, nullptr);
                last->previous = &temp;
                first = &temp;
                std::cout << first << "-" << last << std::endl;

            }
            else {

                Node<T> temp(value, first, nullptr);
                first->previous = &temp;
                first = &temp;

            }


        }

    }

    void add(T value) override {
        std::cout << "LOL" << std::endl;

        if (first == nullptr) {
            std::cout << "First element add" << std::endl;
            Node<T> temp(value, nullptr, nullptr);

            first = &temp;
            last = first;
            std::cout << "end of add first item" << std::endl;
        }
        else {

            if (first == last) {

                std::cout << "First and last are same! add-> " << first << "-" << last << std::endl;
                Node<T> temp(value, nullptr, first);
                first->next = &temp;
                last = &temp;
            }
            else {

                Node<T> temp(value, nullptr, last);
                last->next = &temp;
                last = &temp;

            }



        }


    }

    T remove_front() {

        if (first != nullptr) {
            T te = first->content;
            Node<T>* temp = first;

            first = first->next;

            return te;
        }

        return NULL;
    }

    T remove() override {

        if (last != nullptr) {
            Node<T>* temp = last;
            T te = last->content;
            last = last->previous;
            last->next = nullptr;

            return te;
        }

        return NULL;

    }

    bool isEmpty() override {

        return (first == nullptr);

    }

    bool contains(T value) override {

        Node<T>* temp = first;

        while (temp != nullptr) {

            if (temp->content == value) return true;
            temp = temp->next;

        }

        return false;

    }

    void clear() override {

        Node<T>* temp = first->next;

        while (temp != nullptr) {

            first = temp;
            temp = temp->next;

        }

    }

    int getSize() override {
        int counter = 0;
        Node<T>* temp = first;

        while (temp != nullptr) {

            counter++;
            temp = temp->next;
        }

        return counter;

    }

    Node<int>* getFirst() const {
        return first;
    }
    Node<int>* getLast() const {
        return last;
    }

    friend std::ostream& operator<<(std::ostream& os, const List<int>& l);

};

std::ostream& operator<<(std::ostream& stream, const List<int>& l) {
    std::cout << "Output called" << std::endl;
    Node<int>* temp = l.getLast();


    while (temp != nullptr) {

        std::cout << "Schleife betreten" << std::endl;
        stream << temp->content << " ";



        temp = temp->previous;

    }

    stream << std::endl;

    return stream;
}

collection.hpp

#pragma once
template <typename T>
class Collection {

    virtual void add(T value) = 0;
    virtual int remove() = 0;
    virtual bool isEmpty() = 0;
    virtual bool contains(T obj) = 0;
    virtual void clear() = 0;
    virtual int getSize() = 0;


};

node.hpp

#pragma once
template <typename T>
class Node {


public:
    Node<T>* next;
    Node<T>* previous;
    T content;

    Node(T value, Node<T>* next, Node<T>* previous) {

        content = value;
        this->next = next;
        this->previous = previous;


    }

    ~Node() {

    }


};

我已经看了好几遍了,但还是得到同样的错误。
我用Visual Studio调试了我的程序,collectortest.cpp创建了列表,并使用add()函数添加了第一个值。在调试器中,我看到了如何创建temp节点,如何将first设置为temp的地址,以及如何将last设置为相同的地址。当我们到达“end of add first item”应该打印到控制台的行时,变量发生了变化,为什么?
您可以在此图像中看到变量如何都具有适当的值:
输出前:

但是,当我离开我设置在“end of add first item”的断点时,会发生这种情况:
输出后:

一定有什么东西我没有看到,因为这完全没有意义。我到处都找过了,也许这只是一些非常愚蠢的东西,但我真的在我的极限这里。
你们谁能帮忙解释一下问题出在哪里吗?
我试图执行我的程序并适当地创建节点,但是在内存中出现了一个奇怪的错误。

axr492tv

axr492tv1#

来自@Wyck:

Node<T> temp(value, nullptr, nullptr);
first = &temp;

你正在使用一个指针指向在堆栈上分配的东西,当它超出作用域时,无论你是否注意到它曾经所在的地址,它都将被销毁/无效。
来自@user4581301:

Node<T> temp(value, nullptr, nullptr);
first = &temp;

是您越来越不希望使用new的时候之一。

first = new Node<T>(value, nullptr, nullptr);

来自@TedLyngmo:
对于@Wyck提到的问题,需要使用new/delete动态分配和释放内存。
这些是作为问题的注解发布的答案。我的Node总是因为超出范围而被销毁。我需要使用new,这样它们就可以存储在堆中,并且在超出范围时不会自动销毁。
编辑:我不能选择我自己的答案是正确的2天,所以这个问题可悲的是保持开放。

相关问题